From 477dedc014136ffdff144c2877a73480593c5a79 Mon Sep 17 00:00:00 2001 From: Remuchi <72476615+Remuchi@users.noreply.github.com> Date: Sat, 2 Mar 2024 21:17:52 +0700 Subject: [PATCH] =?UTF-8?q?[Feat]=20Mindslave=20-=20=D0=B8=D0=BC=D0=BF?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D1=82=20=D0=BF=D0=BE=D0=B4=D1=87=D0=B8=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * tweak: стандартизация названий имплантеров * add: mindslave implant * add: briefing, uplink listing, overlay icons * add: new mindslave overlay icons by JustNemo * remove: ненужный файлик удалён * fix: фикс доставания импланта подчинения --- .../Overlays/ShowMindslaveIconsSystem.cs | 67 +++++++++ .../Implants/Mindslave/MindslaveSystem.cs | 85 +++++++++++ .../Implants/SharedImplanterSystem.cs | 138 ++++++++++-------- .../Implants/SharedSubdermalImplantSystem.cs | 2 +- .../Components/MindSlaveComponent.cs | 21 +++ .../Mindslave/SharedMindslaveSystem.cs | 54 +++++++ .../ru-RU/_white/implants/mindslave.ftl | 16 ++ .../ru-RU/locales-new/autotranslate-27.ftl | 38 ++--- .../ru-RU/locales-new/autotranslate-28.ftl | 10 -- .../entities/objects/misc/implanters.ftl | 75 ++++++---- .../objects/misc/subdermal_implants.ftl | 10 ++ .../Locale/ru-RU/store/uplink-catalog.ftl | 6 +- .../ru-RU/white/items/hardlight_spear.ftl | 10 +- .../Entities/Objects/Misc/implanters.yml | 30 ++-- Resources/Prototypes/White/Catalog/uplink.yml | 10 ++ .../Entities/Objects/Misc/implanters.yml | 20 ++- .../Objects/Misc/subdermal_implants.yml | 13 ++ Resources/Prototypes/White/tags.yml | 3 + .../_White/StatusIcon/mindslave.yml | 15 ++ .../White/Overlays/mindslave.rsi/master.png | Bin 0 -> 260 bytes .../White/Overlays/mindslave.rsi/meta.json | 17 +++ .../White/Overlays/mindslave.rsi/slave.png | Bin 0 -> 251 bytes 22 files changed, 494 insertions(+), 146 deletions(-) create mode 100644 Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs create mode 100644 Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs create mode 100644 Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs create mode 100644 Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs create mode 100644 Resources/Locale/ru-RU/_white/implants/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/ShowMindslaveIconsSystem.cs b/Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs new file mode 100644 index 0000000000..90c044e0d3 --- /dev/null +++ b/Content.Client/_White/Overlays/ShowMindslaveIconsSystem.cs @@ -0,0 +1,67 @@ +using Content.Client.Overlays; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Client.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client._White.Overlays; + +public sealed class ShowMindslaveIconsSystem : 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) + { + return; + } + var localEnt = _player.LocalEntity; + if (!TryComp(localEnt, 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; + if (GetEntity(mindSlave.Master) == uid) + { + iconType = mindSlave.MasterStatusIcon; + } + else if (mindSlave.Slaves.Contains(GetNetEntity(uid))) + { + iconType = mindSlave.SlaveStatusIcon; + } + else + { + return result; + } + + if (_prototype.TryIndex(iconType, out var mindslaveIcon)) + { + result.Add(mindslaveIcon); + } + + return result; + } +} diff --git a/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs b/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs new file mode 100644 index 0000000000..d2e1f7e733 --- /dev/null +++ b/Content.Server/_White/Implants/Mindslave/MindslaveSystem.cs @@ -0,0 +1,85 @@ +using Content.Server.Chat.Managers; +using Content.Server.Roles; +using Content.Server.Roles.Jobs; +using Content.Shared._White.Implants.Mindslave; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.Chat; +using Content.Shared.Implants; +using Content.Shared.Implants.Components; + +namespace Content.Server._White.Implants.Mindslave; + +public sealed class MindslaveSystem : SharedMindslaveSystem +{ + [Dependency] private readonly RoleSystem _role = default!; + [Dependency] private readonly IChatManager _chatManager = default!; + [Dependency] private readonly JobSystem _job = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMindslaveInserted); + SubscribeLocalEvent(OnMindslaveRemoved); + } + + private void OnMindslaveInserted(Entity ent, ref SubdermalImplantInserted args) + { + if (!Tag.HasTag(ent.Owner, MindslaveTag)) + { + return; + } + + var slaveComponent = EnsureComp(args.Target); + slaveComponent.Slaves.Add(GetNetEntity(args.Target)); + slaveComponent.Master = GetNetEntity(args.User); + + var masterComponent = EnsureComp(args.User); + masterComponent.Slaves.Add(GetNetEntity(args.Target)); + masterComponent.Master = GetNetEntity(args.User); + + Dirty(args.Target, masterComponent); + + if (!Mind.TryGetMind(args.Target, out var targetMindId, out var targetMind) || targetMind.Session is null) + { + return; + } + + var jobName = _job.MindTryGetJobName(args.User); + + // send message to chat + var message = Loc.GetString("mindslave-chat-message", ("player", args.User), ("role", jobName)); + var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + _chatManager.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", args.User), ("role", jobName)); + Dirty(targetMindId, roleBriefing); + } + else + { + _role.MindAddRole(targetMindId, new RoleBriefingComponent + { + Briefing = Loc.GetString("mindslave-briefing", ("player", args.User), ("role", jobName)) + }, targetMind); + } + } + + private void OnMindslaveRemoved(Entity ent, ref SubdermalImplantRemoved args) + { + if (!TryComp(args.Target, out MindSlaveComponent? mindslave)) + { + return; + } + + if (Mind.TryGetMind(args.Target, out var mindId, out _)) + { + _role.MindTryRemoveRole(mindId); + Popup.PopupEntity(Loc.GetString("mindslave-freed", ("player", mindslave.Master)), args.Target, args.Target); + } + + RemComp(args.Target); + } +} \ No newline at end of file diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 31cc40b3a0..2728709606 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -1,5 +1,4 @@ using System.Diagnostics.CodeAnalysis; -using System.Linq; using Content.Shared.Containers.ItemSlots; using Content.Shared.DoAfter; using Content.Shared.Examine; @@ -15,24 +14,46 @@ using Robust.Shared.Utility; namespace Content.Shared.Implants; //WD EDIT START -public class SubdermalImplantInserted +public sealed class SubdermalImplantInserted { - public EntityUid Entity; + /// + /// Entity who implants + /// + public EntityUid User; + + /// + /// Entity being implanted + /// + public EntityUid Target; + public SubdermalImplantComponent Component; - public SubdermalImplantInserted(EntityUid entity, SubdermalImplantComponent component) + + public SubdermalImplantInserted(EntityUid user, EntityUid target, SubdermalImplantComponent component) { - Entity = entity; + User = user; + Target = target; Component = component; } } -public class SubdermalImplantRemoved +public sealed class SubdermalImplantRemoved { - public EntityUid Entity; + /// + /// Entity who removes implant + /// + public EntityUid User; + + /// + /// Entity which implant is removing + /// + public EntityUid Target; + public SubdermalImplantComponent Component; - public SubdermalImplantRemoved(EntityUid entity, SubdermalImplantComponent component) + + public SubdermalImplantRemoved(EntityUid user, EntityUid target, SubdermalImplantComponent component) { - Entity = entity; + User = user; + Target = target; Component = component; } } @@ -90,10 +111,11 @@ public abstract class SharedImplanterSystem : EntitySystem if (component.ImplanterSlot.ContainerSlot != null) _container.Remove(implant.Value, component.ImplanterSlot.ContainerSlot); + implantComp.ImplantedEntity = target; implantContainer.OccludesLight = false; _container.Insert(implant.Value, implantContainer); - RaiseLocalEvent(new SubdermalImplantInserted(implantComp.ImplantedEntity!.Value, implantComp)); //WD EDIT + RaiseLocalEvent(implant.Value, new SubdermalImplantInserted(user, target, implantComp)); //WD EDIT if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) DrawMode(implanter, component); @@ -103,7 +125,7 @@ public abstract class SharedImplanterSystem : EntitySystem var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; RaiseLocalEvent(target, ref ev); - Dirty(component); + Dirty(implanter, component); } public bool CanImplant( @@ -146,45 +168,47 @@ public abstract class SharedImplanterSystem : EntitySystem var permanentFound = false; - if (_container.TryGetContainer(target, ImplanterComponent.ImplantSlotId, out var implantContainer)) + if (!_container.TryGetContainer(target, ImplanterComponent.ImplantSlotId, out var implantContainer)) + return; + + var implantCompQuery = GetEntityQuery(); + + foreach (var implant in implantContainer.ContainedEntities) { - var implantCompQuery = GetEntityQuery(); + if (!implantCompQuery.TryGetComponent(implant, out var implantComp)) + continue; - foreach (var implant in implantContainer.ContainedEntities) + //Don't remove a permanent implant and look for the next that can be drawn + if (!_container.CanRemove(implant, implantContainer)) { - if (!implantCompQuery.TryGetComponent(implant, out var implantComp)) - continue; + var implantName = Identity.Entity(implant, EntityManager); + var targetName = Identity.Entity(target, EntityManager); + var failedPermanentMessage = Loc.GetString("implanter-draw-failed-permanent", + ("implant", implantName), ("target", targetName)); - //Don't remove a permanent implant and look for the next that can be drawn - if (!_container.CanRemove(implant, implantContainer)) - { - var implantName = Identity.Entity(implant, EntityManager); - var targetName = Identity.Entity(target, EntityManager); - var failedPermanentMessage = Loc.GetString("implanter-draw-failed-permanent", - ("implant", implantName), ("target", targetName)); - _popup.PopupEntity(failedPermanentMessage, target, user); - permanentFound = implantComp.Permanent; - continue; - } - - _container.Remove(implant, implantContainer); - RaiseLocalEvent(new SubdermalImplantRemoved(implantComp.ImplantedEntity!.Value, implantComp)); // WD EDIT - implantComp.ImplantedEntity = null; - _container.Insert(implant, implanterContainer); + _popup.PopupEntity(failedPermanentMessage, target, user); permanentFound = implantComp.Permanent; - - var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; - RaiseLocalEvent(target, ref ev); - - //Break so only one implant is drawn - break; + continue; } - if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound) - ImplantMode(implanter, component); + RaiseLocalEvent(implant, new SubdermalImplantRemoved(user, target, implantComp)); // WD EDIT + _container.Remove(implant, implantContainer); - Dirty(component); + implantComp.ImplantedEntity = null; + _container.Insert(implant, implanterContainer); + permanentFound = implantComp.Permanent; + + var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; + RaiseLocalEvent(target, ref ev); + + //Break so only one implant is drawn + break; } + + if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound) + ImplantMode(implanter, component); + + Dirty(implanter, component); } private void ImplantMode(EntityUid uid, ImplanterComponent component) @@ -204,26 +228,24 @@ public abstract class SharedImplanterSystem : EntitySystem if (!TryComp(uid, out var appearance)) return; - bool implantFound; + var implantFound = component.ImplanterSlot.HasItem; - if (component.ImplanterSlot.HasItem) - implantFound = true; - - else - implantFound = false; - - if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); - - else if (component.CurrentMode == ImplanterToggleMode.Inject && component.ImplantOnly) + switch (component.CurrentMode) { - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); - _appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, - appearance); - } + case ImplanterToggleMode.Inject when !component.ImplantOnly: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + case ImplanterToggleMode.Inject when component.ImplantOnly: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + _appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, + appearance); - else - _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + case ImplanterToggleMode.Draw: + default: + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + break; + } } } diff --git a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs index ebe810546c..e5ba0a1961 100644 --- a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs +++ b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs @@ -136,7 +136,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem var implantContainer = implantedComp.ImplantContainer; component.ImplantedEntity = target; - RaiseLocalEvent(new SubdermalImplantInserted(target, component)); + RaiseLocalEvent(implant, new SubdermalImplantInserted(target, target, component)); _container.Insert(implant, implantContainer); } diff --git a/Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs b/Content.Shared/_White/Implants/Mindslave/Components/MindSlaveComponent.cs new file mode 100644 index 0000000000..48ec51b909 --- /dev/null +++ b/Content.Shared/_White/Implants/Mindslave/Components/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.Components; + +[RegisterComponent, AutoGenerateComponentState, NetworkedComponent] +public sealed partial class MindSlaveComponent : Component +{ + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public List Slaves = new(); + + [ViewVariables(VVAccess.ReadOnly), AutoNetworkedField] + public NetEntity Master; + + [DataField("slaveStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string SlaveStatusIcon = "SlaveMindslaveIcon"; + + [DataField("masterStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MasterStatusIcon = "MasterMindslaveIcon"; +} diff --git a/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs b/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs new file mode 100644 index 0000000000..fe1e266cf3 --- /dev/null +++ b/Content.Shared/_White/Implants/Mindslave/SharedMindslaveSystem.cs @@ -0,0 +1,54 @@ +using Content.Shared._White.Cult.Components; +using Content.Shared._White.Implants.Mindslave.Components; +using Content.Shared.Implants; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Content.Shared.Mindshield.Components; +using Content.Shared.Popups; +using Content.Shared.Tag; + +namespace Content.Shared._White.Implants.Mindslave; + +public abstract class SharedMindslaveSystem : EntitySystem +{ + [Dependency] protected readonly TagSystem Tag = default!; + [Dependency] protected readonly SharedMindSystem Mind = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + + protected const string MindslaveTag = "MindSlave"; + + public override void Initialize() + { + SubscribeLocalEvent(OnTryInsertMindslave); + } + + private void OnTryInsertMindslave(Entity ent, ref AddImplantAttemptEvent args) + { + if (!Tag.HasTag(args.Implant, MindslaveTag)) + { + return; + } + + string message; + string wrappedMessage; + if (args.Target == args.User) + { + message = Loc.GetString("mindslave-target-self"); + wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + Popup.PopupClient(wrappedMessage, args.Implanter, args.User); + args.Cancel(); + return; + } + + if (HasComp(args.Target) || + HasComp(args.Target) || + HasComp(args.Target) || + HasComp(args.Target)) + { + message = Loc.GetString("mindslave-cant-insert"); + wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message)); + Popup.PopupClient(wrappedMessage, args.Implanter, args.User); + args.Cancel(); + } + } +} diff --git a/Resources/Locale/ru-RU/_white/implants/mindslave.ftl b/Resources/Locale/ru-RU/_white/implants/mindslave.ftl new file mode 100644 index 0000000000..8d98357654 --- /dev/null +++ b/Resources/Locale/ru-RU/_white/implants/mindslave.ftl @@ -0,0 +1,16 @@ +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/locales-new/autotranslate-27.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl index eb9eff115c..bdac67fb6c 100644 --- a/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl +++ b/Resources/Locale/ru-RU/locales-new/autotranslate-27.ftl @@ -1,38 +1,28 @@ ent-EggSpider = яичный паук - .desc = Это драгоценный камень? Это яйцо? это выглядит дорого. + .desc = Это драгоценный камень? Это яйцо? это выглядит дорого. ent-LampInterrogator = лампа следователя - .desc = Ультраяркая лампа для плохого полицейского + .desc = Ультраяркая лампа для плохого полицейского ent-CultistCuffs = самодельные стяжки - .desc = Самодельные наручники из запасных тросов. + .desc = Самодельные наручники из запасных тросов. ent-ParamedicIDCard = ID карта парамедика - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-BrigmedicIDCard = ID карта бригмедика - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorEngineerIDCard = ID карта бригадира - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorResearcherIDCard = ID карта ведущего исследователя - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorPhysicianIDCard = ID карта медицинского офицера - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorOfficerIDCard = ID карта ветерана СБ - .desc = { ent-IDCardStandard.desc } + .desc = { ent-IDCardStandard.desc } ent-SeniorSalvageSpecialistIDCard = ID карта охотника карго - .desc = { ent-IDCardStandard.desc } -ent-BikeHornImplanter = имплантат велосипедного гудка - .desc = "" -ent-UplinkImplanter = имплантат аплинка - .desc = "" -ent-EmpImplanter = ЭМИ-имплантат - .desc = "" -ent-DnaScramblerImplanter = имплантат скремблера ДНК - .desc = "" -ent-DeathRattleImplanter = имплантат предсмертных хрипов - .desc = "" + .desc = { ent-IDCardStandard.desc } ent-ModularReceiver = модульный приемник - .desc = Жизненно важная часть, используемая в создании огнестрельного оружия. + .desc = Жизненно важная часть, используемая в создании огнестрельного оружия. ent-RifleStock = приклад - .desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия. + .desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия. ent-MedalCase = футляр для медали - .desc = Футляр с медалями. + .desc = Футляр с медалями. ent-SyndicateSpongeBox = коробка куба обезьяны - .desc = Обезьяньи кубики марки Drymate. Просто добавь воды! + .desc = Обезьяньи кубики марки Drymate. Просто добавь воды! diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl index 60c39f6356..e2a4dbb090 100644 --- a/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl +++ b/Resources/Locale/ru-RU/locales-new/autotranslate-28.ftl @@ -20,16 +20,6 @@ ent-SpiderWeb = паутина .desc = Она тягучая и липкая. ent-SpiderWebClown = клоунская паутина .desc = Она тягучая и липкая. -ent-BikeHornImplant = имплантат велосипедного гудка - .desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время. -ent-UplinkImplant = имплантат аплинка - .desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката. -ent-EmpImplant = ЭМИ-имплантат - .desc = Этот имплантат создает электромагнитный импульс при активации. -ent-DnaScramblerImplant = имплантат скремблера ДНК - .desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя. -ent-DeathRattleImplant = имплантат предсмертных хрипов - .desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет. ent-FloorTileItemFlesh = пол из плоти .desc = { ent-FloorTileItemBase.desc } ent-AmeJar = топливный бак ДАМ'а diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl index 894d4165fb..07672cfe3b 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/implanters.ftl @@ -1,33 +1,54 @@ ent-BaseImplanter = имплантер .desc = Специальный шприц, используемый только для имплантов. - .suffix = { "" } ent-Implanter = { ent-BaseImplanter } .desc = { ent-BaseImplanter.desc } - .suffix = { "" } ent-BaseImplantOnlyImplanter = { ent-Implanter } .desc = Одноразовый имплантер. - .suffix = { "" } -ent-SadTromboneImplanter = имплантер Грустный тромбон - .desc = Одноразовый имплантер, содержащий имплант, который проигрывает грустную мелодию при смерти владельца. - .suffix = { "" } -ent-LightImplanter = имплантер Свет - .desc = Одноразовый имплантер, содержащий имплант, который излучает свет при активации. - .suffix = { "" } -ent-TrackingImplanter = имплантер Отслеживание - .desc = Одноразовый имплантер, содержащий имплант, постоянно передающий координаты владельца. - .suffix = { "" } -ent-StorageImplanter = имплантер Хранилище - .desc = Одноразовый имплантер, содержащий имплант, создающий хранилище в теле владельца. - .suffix = { "" } -ent-FreedomImplanter = имплантер Свобода - .desc = Одноразовый имплантер, содержащий имплант, позволяющий владельцу три раза освободиться от наручников и других ограничителей. - .suffix = { "" } -ent-MicroBombImplanter = имплантер Микробомба - .desc = Одноразовый имплантер, содержащий неизвлекаемый имплант, вызывающий небольшой взрыв при смерти владельца. - .suffix = { "" } -ent-MacroBombImplanter = имплантер Макробомба - .desc = Одноразовый имплантер, содержащий имплант, вызывающий мощный взрыв при смерти владельца по истечении заданного времени. - .suffix = { "" } -ent-MindshieldImplanter = имплантер Защиты Разума - .desc = Одноразовый имплантер, содержащий имплант защиты разума. - .suffix = { "" } +ent-SadTromboneImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = грустный тромбон +ent-LightImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = свет +ent-TrackingImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = отслеживание +ent-StorageImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = хранилище +ent-FreedomImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = свобода +ent-MicroBombImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = микробомба +ent-MacroBombImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = макробомба +ent-MindShieldImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = защита разума +ent-BikeHornImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = велосипедный гудок +ent-UplinkImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = аплинк +ent-EmpImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = ЭМИ +ent-DnaScramblerImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = скремблер ДНК +ent-DeathRattleImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = предсмертный хрип +ent-ScramImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = переброска +ent-DeathAcidifierImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = посмертный растворитель +ent-ImplanterAdmeme = { ent-BaseImplanter } + .desc = {""} + .suffix = адмемы diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl index 1931cab724..69213ef1f3 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/misc/subdermal_implants.ftl @@ -25,3 +25,13 @@ ent-MacroBombImplant = имплант Макробомба ent-MindShieldImplant = имплант Защиты Разума .desc = Маленький имплант, который защищает мозги носителя от промывки. .suffix = { "" } +ent-BikeHornImplant = имплант велосипедного гудка + .desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время. +ent-UplinkImplant = имплант аплинка + .desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката. +ent-EmpImplant = ЭМИ-имплант + .desc = Этот имплантат создает электромагнитный импульс при активации. +ent-DnaScramblerImplant = имплант скремблера ДНК + .desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя. +ent-DeathRattleImplant = имплант предсмертных хрипов + .desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет. diff --git a/Resources/Locale/ru-RU/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/store/uplink-catalog.ftl index cd81a8a648..dcbed400e5 100644 --- a/Resources/Locale/ru-RU/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/store/uplink-catalog.ftl @@ -181,7 +181,7 @@ uplink-freedom-implanter-name = Имплант свободы uplink-freedom-implanter-desc = Убирайся подальше от этих мерзких офицеров с этим имплантатом! uplink-scram-implanter-name = Имплант переброски -uplink-scram-implanter-desc = Имплантат 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено. +uplink-scram-implanter-desc = Имплант 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено. uplink-dna-scrambler-implanter-name = Имплант скремблера ДНК uplink-dna-scrambler-implanter-desc = Одноразовый имплантат, который можно активировать, чтобы изменить вашу ДНК и придать вам совершенно новый вид, также имеет функцию отмены изменений. Невозможно зашифровать уже зашифрованную ДНК. @@ -198,10 +198,10 @@ uplink-uplink-implanter-desc = Незаметно заказывайте обо uplink-deathrattle-implant-name = Коробка имплантатов предсмертного хрипа uplink-deathrattle-implant-desc = Коробка с достаточным количеством предсмертных хрипов для всего отряда. Передает сообщение, содержащее вашу позицию, на канал синдиката, когда вы переходите в критическое состояние или умираете. -uplink-death-acidifier-implant-name = Имплантат расплавления +uplink-death-acidifier-implant-name = Имплантер расплавления uplink-death-acidifier-implant-desc = Полностью расплавляет пользователя и его снаряжение при использовании или смерти. -uplink-micro-bomb-implanter-name = Имплантатор микро-бомбы +uplink-micro-bomb-implanter-name = Имплантер микро-бомбы uplink-micro-bomb-implanter-desc = Взорвитесь при смерти или ручной активации с помощью этого имплантата. Уничтожает тело со всем снаряжением. # Bundles diff --git a/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl b/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl index 3e6d783a7a..421650fba6 100644 --- a/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl +++ b/Resources/Locale/ru-RU/white/items/hardlight_spear.ftl @@ -1,13 +1,19 @@ hardlight-spear-pickup-failed = Вы не можете подобрать световое копьё. use-hardlight-spear-implant-action-name = Создать световое копьё. use-hardlight-spear-implant-action-description = Создает световое копьё в ваших руках. -uplink-hardlight-spear-implant-name = Имплантатор световое копьё +uplink-hardlight-spear-implant-name = Имплантер световое копьё uplink-hardlight-spear-implant-desc = Имплант, вводимый в тело и активируемый по желанию пользователя. Он вызывает копье из твердого света, с помощью которого пользователь может сеять хаос. ent-SpearHardlight = световое копьё .desc = Копьё из твердого света. -ent-HardlightSpearImplanter = имплантатор световое копьё +ent-HardlightSpearImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = световое копьё ent-HardlightSpearImplant = имплант световое копьё .desc = Этот имплант создаёт световое копьё в ваших руках. + +ent-SmokeImplanter = { ent-BaseImplanter } + .desc = {""} + .suffix = дым diff --git a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml index 4a7115c2d7..4d0e877290 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/implanters.yml @@ -124,24 +124,24 @@ - type: entity id: SadTromboneImplanter - name: sad trombone implanter parent: BaseImplantOnlyImplanter + suffix: sad trombone components: - type: Implanter implant: SadTromboneImplant - type: entity id: LightImplanter - name: light implanter parent: BaseImplantOnlyImplanter + suffix: light components: - type: Implanter implant: LightImplant - type: entity id: BikeHornImplanter - name: bike horn implanter parent: BaseImplantOnlyImplanter + suffix: bike horn components: - type: Implanter implant: BikeHornImplant @@ -150,8 +150,8 @@ - type: entity id: TrackingImplanter - name: tracking implanter parent: BaseImplantOnlyImplanter + suffix: tracking components: - type: Implanter implant: TrackingImplant @@ -160,24 +160,24 @@ - type: entity id: StorageImplanter - name: storage implanter parent: BaseImplantOnlyImplanterSyndi + suffix: storage components: - type: Implanter implant: StorageImplant - type: entity id: FreedomImplanter - name: freedom implanter parent: BaseImplantOnlyImplanterSyndi + suffix: freedom components: - type: Implanter implant: FreedomImplant - type: entity id: UplinkImplanter - name: uplink implanter parent: BaseImplantOnlyImplanterSyndi + suffix: uplink components: - type: Implanter implant: UplinkImplant @@ -185,24 +185,24 @@ - type: entity id: EmpImplanter - name: EMP implanter parent: BaseImplantOnlyImplanterSyndi + suffix: EMP components: - type: Implanter implant: EmpImplant - type: entity id: ScramImplanter - name: scram implanter parent: BaseImplantOnlyImplanterSyndi + suffix: scram components: - type: Implanter implant: ScramImplant - type: entity id: DnaScramblerImplanter - name: DNA scrambler implanter parent: BaseImplantOnlyImplanterSyndi + suffix: DNA scrambler components: - type: Implanter implant: DnaScramblerImplant @@ -211,32 +211,32 @@ - type: entity id: MicroBombImplanter - name: micro-bomb implanter parent: BaseImplantOnlyImplanterSyndi + suffix: micro-bomb components: - type: Implanter implant: MicroBombImplant - type: entity id: MacroBombImplanter - name: macro-bomb implanter parent: BaseImplantOnlyImplanterSyndi + suffix: macro-bomb components: - type: Implanter implant: MacroBombImplant - type: entity id: DeathRattleImplanter - name: death rattle implanter parent: BaseImplantOnlyImplanterSyndi + suffix: death rattle components: - type: Implanter implant: DeathRattleImplant - type: entity id: DeathAcidifierImplanter - name: death acidifier implanter parent: BaseImplantOnlyImplanterSyndi + suffix: death acidifier components: - type: Implanter implant: DeathAcidifierImplant @@ -245,8 +245,8 @@ - type: entity id: MindShieldImplanter - name: mind-shield implanter parent: BaseImplantOnlyImplanter + suffix: mind-shield components: - type: Implanter implant: MindShieldImplant diff --git a/Resources/Prototypes/White/Catalog/uplink.yml b/Resources/Prototypes/White/Catalog/uplink.yml index 9c6da52d4c..9bb495ac41 100644 --- a/Resources/Prototypes/White/Catalog/uplink.yml +++ b/Resources/Prototypes/White/Catalog/uplink.yml @@ -204,3 +204,13 @@ Telecrystal: 1 categories: - UplinkAmmo + +- type: listing + id: UplinkMindSlaveImplanter + name: uplink-mind-slave + description: uplink-mind-slave-desc + 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 4970be67b5..8bbbcf60e7 100644 --- a/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/White/Entities/Objects/Misc/implanters.yml @@ -1,15 +1,23 @@ - type: entity id: SmokeImplanter - name: имплант дыма parent: BaseImplantOnlyImplanterSyndi + suffix: smoke components: - - type: Implanter - implant: SmokeImplant + - type: Implanter + implant: SmokeImplant - type: entity id: HardlightSpearImplanter - name: hardlight spear implanter parent: BaseImplantOnlyImplanterSyndi + suffix: hardlight spear components: - - type: Implanter - implant: HardlightSpearImplant + - type: Implanter + implant: HardlightSpearImplant + +- type: entity + id: MindSlaveImplanter + parent: BaseImplantOnlyImplanterSyndi + 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 686d3b4283..b916ec534f 100644 --- a/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/White/Entities/Objects/Misc/subdermal_implants.yml @@ -23,3 +23,16 @@ components: - type: SubdermalImplant implantAction: ActivateHardlightSpearImplant + +- 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 + diff --git a/Resources/Prototypes/White/tags.yml b/Resources/Prototypes/White/tags.yml index fc6f00c9af..466a1ddb17 100644 --- a/Resources/Prototypes/White/tags.yml +++ b/Resources/Prototypes/White/tags.yml @@ -51,3 +51,6 @@ - type: Tag id: WeldedKnife + +- type: Tag + id: MindSlave diff --git a/Resources/Prototypes/_White/StatusIcon/mindslave.yml b/Resources/Prototypes/_White/StatusIcon/mindslave.yml new file mode 100644 index 0000000000..9af545c195 --- /dev/null +++ b/Resources/Prototypes/_White/StatusIcon/mindslave.yml @@ -0,0 +1,15 @@ +- type: statusIcon + id: MasterMindslaveIcon + priority: 3 + locationPreference: Left + icon: + sprite: /Textures/White/Overlays/mindslave.rsi + state: master + +- type: statusIcon + id: SlaveMindslaveIcon + priority: 3 + locationPreference: Left + icon: + sprite: /Textures/White/Overlays/mindslave.rsi + state: slave 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..56416298ef956c274f9fccab0c49a7f9bc0e1046 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJjh-%!ArYL(TTH(EJKw-AW50i@ zV86-HARh%`r=v2GDL+*um-(J$O%{+=apOP0wCTx_^U^$1a}{~mroBtB*1jzvaclLp z3y162*aAf6*l&AmZ^h6l*d>>>LqLYrV1B#xGNT3qjsr(lByz?XJM7~r_Hg89*dTG& z=|EE~^Ba#R0u7xHOKn9}4o31!_s^Wmy7IxlKxH@Q1QQl)M4KZA1H%;t@5B4+>K+3f g&zBnEnda-upaoFVdQ&MBb@04V!W-2eap literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Overlays/mindslave.rsi/meta.json b/Resources/Textures/White/Overlays/mindslave.rsi/meta.json new file mode 100644 index 0000000000..3786e26e8d --- /dev/null +++ b/Resources/Textures/White/Overlays/mindslave.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "@JustNemo", + "states": [ + { + "name": "slave" + }, + { + "name": "master" + } + ] +} diff --git a/Resources/Textures/White/Overlays/mindslave.rsi/slave.png b/Resources/Textures/White/Overlays/mindslave.rsi/slave.png new file mode 100644 index 0000000000000000000000000000000000000000..3739880d22873569594c5ac942c696184debe43a GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6`n4RArYL(TTH(EJKw-AW50i@ zV86-HARPr^r=v2GGOtSmcy8aXXifaO`maXPmIn>844Y(96pa`<*PdIpmwAT6G^vPP z&2P6&Pf2G;OffWQZ)3T^sPH*aZ1LvI4D%Zq8<@|j`Xw67n$NtQ`v_a-Mdk+Ch8)W? zK{-hVmRXk`=(K5TU$Wv3x~#l7t+(w!21gGTg6FOP1H&Iqd9Adhh%}&^`BEc1(|mmy Yw18|5AO?X;!IMFhr>mdKI;Vst0IFA3U;qFB literal 0 HcmV?d00001