[Feat] Mindslave - имплант подчинения (#152)

* tweak: стандартизация названий имплантеров

* add: mindslave implant

* add: briefing, uplink listing, overlay icons

* add: new mindslave overlay icons by JustNemo

* remove: ненужный файлик удалён

* fix: фикс доставания импланта подчинения
This commit is contained in:
Remuchi
2024-03-02 21:17:52 +07:00
committed by GitHub
parent ba1384faff
commit 477dedc014
22 changed files with 494 additions and 146 deletions

View File

@@ -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<MindSlaveComponent>
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly IPlayerManager _player = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MindSlaveComponent, GetStatusIconsEvent>(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<StatusIconPrototype> MindslaveIcon(EntityUid uid, MindSlaveComponent mindSlave)
{
var result = new List<StatusIconPrototype>();
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<StatusIconPrototype>(iconType, out var mindslaveIcon))
{
result.Add(mindslaveIcon);
}
return result;
}
}

View File

@@ -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<SubdermalImplantComponent, SubdermalImplantInserted>(OnMindslaveInserted);
SubscribeLocalEvent<SubdermalImplantComponent, SubdermalImplantRemoved>(OnMindslaveRemoved);
}
private void OnMindslaveInserted(Entity<SubdermalImplantComponent> ent, ref SubdermalImplantInserted args)
{
if (!Tag.HasTag(ent.Owner, MindslaveTag))
{
return;
}
var slaveComponent = EnsureComp<MindSlaveComponent>(args.Target);
slaveComponent.Slaves.Add(GetNetEntity(args.Target));
slaveComponent.Master = GetNetEntity(args.User);
var masterComponent = EnsureComp<MindSlaveComponent>(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<RoleBriefingComponent>(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<SubdermalImplantComponent> ent, ref SubdermalImplantRemoved args)
{
if (!TryComp(args.Target, out MindSlaveComponent? mindslave))
{
return;
}
if (Mind.TryGetMind(args.Target, out var mindId, out _))
{
_role.MindTryRemoveRole<RoleBriefingComponent>(mindId);
Popup.PopupEntity(Loc.GetString("mindslave-freed", ("player", mindslave.Master)), args.Target, args.Target);
}
RemComp<MindSlaveComponent>(args.Target);
}
}

View File

@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter; using Content.Shared.DoAfter;
using Content.Shared.Examine; using Content.Shared.Examine;
@@ -15,24 +14,46 @@ using Robust.Shared.Utility;
namespace Content.Shared.Implants; namespace Content.Shared.Implants;
//WD EDIT START //WD EDIT START
public class SubdermalImplantInserted public sealed class SubdermalImplantInserted
{ {
public EntityUid Entity; /// <summary>
/// Entity who implants
/// </summary>
public EntityUid User;
/// <summary>
/// Entity being implanted
/// </summary>
public EntityUid Target;
public SubdermalImplantComponent Component; 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; Component = component;
} }
} }
public class SubdermalImplantRemoved public sealed class SubdermalImplantRemoved
{ {
public EntityUid Entity; /// <summary>
/// Entity who removes implant
/// </summary>
public EntityUid User;
/// <summary>
/// Entity which implant is removing
/// </summary>
public EntityUid Target;
public SubdermalImplantComponent Component; 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; Component = component;
} }
} }
@@ -90,10 +111,11 @@ public abstract class SharedImplanterSystem : EntitySystem
if (component.ImplanterSlot.ContainerSlot != null) if (component.ImplanterSlot.ContainerSlot != null)
_container.Remove(implant.Value, component.ImplanterSlot.ContainerSlot); _container.Remove(implant.Value, component.ImplanterSlot.ContainerSlot);
implantComp.ImplantedEntity = target; implantComp.ImplantedEntity = target;
implantContainer.OccludesLight = false; implantContainer.OccludesLight = false;
_container.Insert(implant.Value, implantContainer); _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) if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly)
DrawMode(implanter, component); DrawMode(implanter, component);
@@ -103,7 +125,7 @@ public abstract class SharedImplanterSystem : EntitySystem
var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; var ev = new TransferDnaEvent { Donor = target, Recipient = implanter };
RaiseLocalEvent(target, ref ev); RaiseLocalEvent(target, ref ev);
Dirty(component); Dirty(implanter, component);
} }
public bool CanImplant( public bool CanImplant(
@@ -146,45 +168,47 @@ public abstract class SharedImplanterSystem : EntitySystem
var permanentFound = false; 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<SubdermalImplantComponent>();
foreach (var implant in implantContainer.ContainedEntities)
{ {
var implantCompQuery = GetEntityQuery<SubdermalImplantComponent>(); 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)) var implantName = Identity.Entity(implant, EntityManager);
continue; 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 _popup.PopupEntity(failedPermanentMessage, target, user);
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);
permanentFound = implantComp.Permanent; permanentFound = implantComp.Permanent;
continue;
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) RaiseLocalEvent(implant, new SubdermalImplantRemoved(user, target, implantComp)); // WD EDIT
ImplantMode(implanter, component); _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) private void ImplantMode(EntityUid uid, ImplanterComponent component)
@@ -204,26 +228,24 @@ public abstract class SharedImplanterSystem : EntitySystem
if (!TryComp<AppearanceComponent>(uid, out var appearance)) if (!TryComp<AppearanceComponent>(uid, out var appearance))
return; return;
bool implantFound; var implantFound = component.ImplanterSlot.HasItem;
if (component.ImplanterSlot.HasItem) switch (component.CurrentMode)
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)
{ {
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); case ImplanterToggleMode.Inject when !component.ImplantOnly:
_appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance);
appearance); break;
} case ImplanterToggleMode.Inject when component.ImplantOnly:
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance);
_appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly,
appearance);
else break;
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); case ImplanterToggleMode.Draw:
default:
_appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance);
break;
}
} }
} }

View File

@@ -136,7 +136,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
var implantContainer = implantedComp.ImplantContainer; var implantContainer = implantedComp.ImplantContainer;
component.ImplantedEntity = target; component.ImplantedEntity = target;
RaiseLocalEvent(new SubdermalImplantInserted(target, component)); RaiseLocalEvent(implant, new SubdermalImplantInserted(target, target, component));
_container.Insert(implant, implantContainer); _container.Insert(implant, implantContainer);
} }

View File

@@ -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<NetEntity> Slaves = new();
[ViewVariables(VVAccess.ReadOnly), AutoNetworkedField]
public NetEntity Master;
[DataField("slaveStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
public string SlaveStatusIcon = "SlaveMindslaveIcon";
[DataField("masterStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
public string MasterStatusIcon = "MasterMindslaveIcon";
}

View File

@@ -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<MindContainerComponent, AddImplantAttemptEvent>(OnTryInsertMindslave);
}
private void OnTryInsertMindslave(Entity<MindContainerComponent> 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<MindShieldComponent>(args.Target) ||
HasComp<MindSlaveComponent>(args.Target) ||
HasComp<CultistComponent>(args.Target) ||
HasComp<Revolutionary.Components.RevolutionaryComponent>(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();
}
}
}

View File

@@ -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 = Сделайте из кого-то свою личную куклу.

View File

@@ -1,38 +1,28 @@
ent-EggSpider = яичный паук ent-EggSpider = яичный паук
.desc = Это драгоценный камень? Это яйцо? это выглядит дорого. .desc = Это драгоценный камень? Это яйцо? это выглядит дорого.
ent-LampInterrogator = лампа следователя ent-LampInterrogator = лампа следователя
.desc = Ультраяркая лампа для плохого полицейского .desc = Ультраяркая лампа для плохого полицейского
ent-CultistCuffs = самодельные стяжки ent-CultistCuffs = самодельные стяжки
.desc = Самодельные наручники из запасных тросов. .desc = Самодельные наручники из запасных тросов.
ent-ParamedicIDCard = ID карта парамедика ent-ParamedicIDCard = ID карта парамедика
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-BrigmedicIDCard = ID карта бригмедика ent-BrigmedicIDCard = ID карта бригмедика
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-SeniorEngineerIDCard = ID карта бригадира ent-SeniorEngineerIDCard = ID карта бригадира
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-SeniorResearcherIDCard = ID карта ведущего исследователя ent-SeniorResearcherIDCard = ID карта ведущего исследователя
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-SeniorPhysicianIDCard = ID карта медицинского офицера ent-SeniorPhysicianIDCard = ID карта медицинского офицера
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-SeniorOfficerIDCard = ID карта ветерана СБ ent-SeniorOfficerIDCard = ID карта ветерана СБ
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-SeniorSalvageSpecialistIDCard = ID карта охотника карго ent-SeniorSalvageSpecialistIDCard = ID карта охотника карго
.desc = { ent-IDCardStandard.desc } .desc = { ent-IDCardStandard.desc }
ent-BikeHornImplanter = имплантат велосипедного гудка
.desc = ""
ent-UplinkImplanter = имплантат аплинка
.desc = ""
ent-EmpImplanter = ЭМИ-имплантат
.desc = ""
ent-DnaScramblerImplanter = имплантат скремблера ДНК
.desc = ""
ent-DeathRattleImplanter = имплантат предсмертных хрипов
.desc = ""
ent-ModularReceiver = модульный приемник ent-ModularReceiver = модульный приемник
.desc = Жизненно важная часть, используемая в создании огнестрельного оружия. .desc = Жизненно важная часть, используемая в создании огнестрельного оружия.
ent-RifleStock = приклад ent-RifleStock = приклад
.desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия. .desc = Прочный деревянный приклад, используемый при создании огнестрельного оружия.
ent-MedalCase = футляр для медали ent-MedalCase = футляр для медали
.desc = Футляр с медалями. .desc = Футляр с медалями.
ent-SyndicateSpongeBox = коробка куба обезьяны ent-SyndicateSpongeBox = коробка куба обезьяны
.desc = Обезьяньи кубики марки Drymate. Просто добавь воды! .desc = Обезьяньи кубики марки Drymate. Просто добавь воды!

View File

@@ -20,16 +20,6 @@ ent-SpiderWeb = паутина
.desc = Она тягучая и липкая. .desc = Она тягучая и липкая.
ent-SpiderWebClown = клоунская паутина ent-SpiderWebClown = клоунская паутина
.desc = Она тягучая и липкая. .desc = Она тягучая и липкая.
ent-BikeHornImplant = имплантат велосипедного гудка
.desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время.
ent-UplinkImplant = имплантат аплинка
.desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката.
ent-EmpImplant = ЭМИ-имплантат
.desc = Этот имплантат создает электромагнитный импульс при активации.
ent-DnaScramblerImplant = имплантат скремблера ДНК
.desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя.
ent-DeathRattleImplant = имплантат предсмертных хрипов
.desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет.
ent-FloorTileItemFlesh = пол из плоти ent-FloorTileItemFlesh = пол из плоти
.desc = { ent-FloorTileItemBase.desc } .desc = { ent-FloorTileItemBase.desc }
ent-AmeJar = топливный бак ДАМ'а ent-AmeJar = топливный бак ДАМ'а

View File

@@ -1,33 +1,54 @@
ent-BaseImplanter = имплантер ent-BaseImplanter = имплантер
.desc = Специальный шприц, используемый только для имплантов. .desc = Специальный шприц, используемый только для имплантов.
.suffix = { "" }
ent-Implanter = { ent-BaseImplanter } ent-Implanter = { ent-BaseImplanter }
.desc = { ent-BaseImplanter.desc } .desc = { ent-BaseImplanter.desc }
.suffix = { "" }
ent-BaseImplantOnlyImplanter = { ent-Implanter } ent-BaseImplantOnlyImplanter = { ent-Implanter }
.desc = Одноразовый имплантер. .desc = Одноразовый имплантер.
.suffix = { "" } ent-SadTromboneImplanter = { ent-BaseImplanter }
ent-SadTromboneImplanter = имплантер Грустный тромбон .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, который проигрывает грустную мелодию при смерти владельца. .suffix = грустный тромбон
.suffix = { "" } ent-LightImplanter = { ent-BaseImplanter }
ent-LightImplanter = имплантер Свет .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, который излучает свет при активации. .suffix = свет
.suffix = { "" } ent-TrackingImplanter = { ent-BaseImplanter }
ent-TrackingImplanter = имплантер Отслеживание .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, постоянно передающий координаты владельца. .suffix = отслеживание
.suffix = { "" } ent-StorageImplanter = { ent-BaseImplanter }
ent-StorageImplanter = имплантер Хранилище .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, создающий хранилище в теле владельца. .suffix = хранилище
.suffix = { "" } ent-FreedomImplanter = { ent-BaseImplanter }
ent-FreedomImplanter = имплантер Свобода .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, позволяющий владельцу три раза освободиться от наручников и других ограничителей. .suffix = свобода
.suffix = { "" } ent-MicroBombImplanter = { ent-BaseImplanter }
ent-MicroBombImplanter = имплантер Микробомба .desc = {""}
.desc = Одноразовый имплантер, содержащий неизвлекаемый имплант, вызывающий небольшой взрыв при смерти владельца. .suffix = микробомба
.suffix = { "" } ent-MacroBombImplanter = { ent-BaseImplanter }
ent-MacroBombImplanter = имплантер Макробомба .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант, вызывающий мощный взрыв при смерти владельца по истечении заданного времени. .suffix = макробомба
.suffix = { "" } ent-MindShieldImplanter = { ent-BaseImplanter }
ent-MindshieldImplanter = имплантер Защиты Разума .desc = {""}
.desc = Одноразовый имплантер, содержащий имплант защиты разума. .suffix = защита разума
.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 = адмемы

View File

@@ -25,3 +25,13 @@ ent-MacroBombImplant = имплант Макробомба
ent-MindShieldImplant = имплант Защиты Разума ent-MindShieldImplant = имплант Защиты Разума
.desc = Маленький имплант, который защищает мозги носителя от промывки. .desc = Маленький имплант, который защищает мозги носителя от промывки.
.suffix = { "" } .suffix = { "" }
ent-BikeHornImplant = имплант велосипедного гудка
.desc = Этот имплантат позволяет пользователю сигналить в любом месте в любое время.
ent-UplinkImplant = имплант аплинка
.desc = Этот имплант позволяет пользователю по желанию получить доступ к скрытому восходящему каналу Синдиката.
ent-EmpImplant = ЭМИ-имплант
.desc = Этот имплантат создает электромагнитный импульс при активации.
ent-DnaScramblerImplant = имплант скремблера ДНК
.desc = Этот имплантат позволяет пользователю один раз случайным образом изменить свой внешний вид и имя.
ent-DeathRattleImplant = имплант предсмертных хрипов
.desc = Этот имплантат сообщит по радиоканалу Синдиката, если пользователь попадет в критическое состояние или умрет.

View File

@@ -181,7 +181,7 @@ uplink-freedom-implanter-name = Имплант свободы
uplink-freedom-implanter-desc = Убирайся подальше от этих мерзких офицеров с этим имплантатом! uplink-freedom-implanter-desc = Убирайся подальше от этих мерзких офицеров с этим имплантатом!
uplink-scram-implanter-name = Имплант переброски uplink-scram-implanter-name = Имплант переброски
uplink-scram-implanter-desc = Имплантат 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено. uplink-scram-implanter-desc = Имплант 2-го использования, который телепортирует вас в большом радиусе. Пытается телепортировать вас в пустое пространство. Иногда может не справиться. Страхование жизни не предусмотрено.
uplink-dna-scrambler-implanter-name = Имплант скремблера ДНК uplink-dna-scrambler-implanter-name = Имплант скремблера ДНК
uplink-dna-scrambler-implanter-desc = Одноразовый имплантат, который можно активировать, чтобы изменить вашу ДНК и придать вам совершенно новый вид, также имеет функцию отмены изменений. Невозможно зашифровать уже зашифрованную ДНК. uplink-dna-scrambler-implanter-desc = Одноразовый имплантат, который можно активировать, чтобы изменить вашу ДНК и придать вам совершенно новый вид, также имеет функцию отмены изменений. Невозможно зашифровать уже зашифрованную ДНК.
@@ -198,10 +198,10 @@ uplink-uplink-implanter-desc = Незаметно заказывайте обо
uplink-deathrattle-implant-name = Коробка имплантатов предсмертного хрипа uplink-deathrattle-implant-name = Коробка имплантатов предсмертного хрипа
uplink-deathrattle-implant-desc = Коробка с достаточным количеством предсмертных хрипов для всего отряда. Передает сообщение, содержащее вашу позицию, на канал синдиката, когда вы переходите в критическое состояние или умираете. uplink-deathrattle-implant-desc = Коробка с достаточным количеством предсмертных хрипов для всего отряда. Передает сообщение, содержащее вашу позицию, на канал синдиката, когда вы переходите в критическое состояние или умираете.
uplink-death-acidifier-implant-name = Имплантат расплавления uplink-death-acidifier-implant-name = Имплантер расплавления
uplink-death-acidifier-implant-desc = Полностью расплавляет пользователя и его снаряжение при использовании или смерти. uplink-death-acidifier-implant-desc = Полностью расплавляет пользователя и его снаряжение при использовании или смерти.
uplink-micro-bomb-implanter-name = Имплантатор микро-бомбы uplink-micro-bomb-implanter-name = Имплантер микро-бомбы
uplink-micro-bomb-implanter-desc = Взорвитесь при смерти или ручной активации с помощью этого имплантата. Уничтожает тело со всем снаряжением. uplink-micro-bomb-implanter-desc = Взорвитесь при смерти или ручной активации с помощью этого имплантата. Уничтожает тело со всем снаряжением.
# Bundles # Bundles

View File

@@ -1,13 +1,19 @@
hardlight-spear-pickup-failed = Вы не можете подобрать световое копьё. hardlight-spear-pickup-failed = Вы не можете подобрать световое копьё.
use-hardlight-spear-implant-action-name = Создать световое копьё. use-hardlight-spear-implant-action-name = Создать световое копьё.
use-hardlight-spear-implant-action-description = Создает световое копьё в ваших руках. use-hardlight-spear-implant-action-description = Создает световое копьё в ваших руках.
uplink-hardlight-spear-implant-name = Имплантатор световое копьё uplink-hardlight-spear-implant-name = Имплантер световое копьё
uplink-hardlight-spear-implant-desc = Имплант, вводимый в тело и активируемый по желанию пользователя. Он вызывает копье из твердого света, с помощью которого пользователь может сеять хаос. uplink-hardlight-spear-implant-desc = Имплант, вводимый в тело и активируемый по желанию пользователя. Он вызывает копье из твердого света, с помощью которого пользователь может сеять хаос.
ent-SpearHardlight = световое копьё ent-SpearHardlight = световое копьё
.desc = Копьё из твердого света. .desc = Копьё из твердого света.
ent-HardlightSpearImplanter = имплантатор световое копьё ent-HardlightSpearImplanter = { ent-BaseImplanter }
.desc = {""}
.suffix = световое копьё
ent-HardlightSpearImplant = имплант световое копьё ent-HardlightSpearImplant = имплант световое копьё
.desc = Этот имплант создаёт световое копьё в ваших руках. .desc = Этот имплант создаёт световое копьё в ваших руках.
ent-SmokeImplanter = { ent-BaseImplanter }
.desc = {""}
.suffix = дым

View File

@@ -124,24 +124,24 @@
- type: entity - type: entity
id: SadTromboneImplanter id: SadTromboneImplanter
name: sad trombone implanter
parent: BaseImplantOnlyImplanter parent: BaseImplantOnlyImplanter
suffix: sad trombone
components: components:
- type: Implanter - type: Implanter
implant: SadTromboneImplant implant: SadTromboneImplant
- type: entity - type: entity
id: LightImplanter id: LightImplanter
name: light implanter
parent: BaseImplantOnlyImplanter parent: BaseImplantOnlyImplanter
suffix: light
components: components:
- type: Implanter - type: Implanter
implant: LightImplant implant: LightImplant
- type: entity - type: entity
id: BikeHornImplanter id: BikeHornImplanter
name: bike horn implanter
parent: BaseImplantOnlyImplanter parent: BaseImplantOnlyImplanter
suffix: bike horn
components: components:
- type: Implanter - type: Implanter
implant: BikeHornImplant implant: BikeHornImplant
@@ -150,8 +150,8 @@
- type: entity - type: entity
id: TrackingImplanter id: TrackingImplanter
name: tracking implanter
parent: BaseImplantOnlyImplanter parent: BaseImplantOnlyImplanter
suffix: tracking
components: components:
- type: Implanter - type: Implanter
implant: TrackingImplant implant: TrackingImplant
@@ -160,24 +160,24 @@
- type: entity - type: entity
id: StorageImplanter id: StorageImplanter
name: storage implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: storage
components: components:
- type: Implanter - type: Implanter
implant: StorageImplant implant: StorageImplant
- type: entity - type: entity
id: FreedomImplanter id: FreedomImplanter
name: freedom implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: freedom
components: components:
- type: Implanter - type: Implanter
implant: FreedomImplant implant: FreedomImplant
- type: entity - type: entity
id: UplinkImplanter id: UplinkImplanter
name: uplink implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: uplink
components: components:
- type: Implanter - type: Implanter
implant: UplinkImplant implant: UplinkImplant
@@ -185,24 +185,24 @@
- type: entity - type: entity
id: EmpImplanter id: EmpImplanter
name: EMP implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: EMP
components: components:
- type: Implanter - type: Implanter
implant: EmpImplant implant: EmpImplant
- type: entity - type: entity
id: ScramImplanter id: ScramImplanter
name: scram implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: scram
components: components:
- type: Implanter - type: Implanter
implant: ScramImplant implant: ScramImplant
- type: entity - type: entity
id: DnaScramblerImplanter id: DnaScramblerImplanter
name: DNA scrambler implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: DNA scrambler
components: components:
- type: Implanter - type: Implanter
implant: DnaScramblerImplant implant: DnaScramblerImplant
@@ -211,32 +211,32 @@
- type: entity - type: entity
id: MicroBombImplanter id: MicroBombImplanter
name: micro-bomb implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: micro-bomb
components: components:
- type: Implanter - type: Implanter
implant: MicroBombImplant implant: MicroBombImplant
- type: entity - type: entity
id: MacroBombImplanter id: MacroBombImplanter
name: macro-bomb implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: macro-bomb
components: components:
- type: Implanter - type: Implanter
implant: MacroBombImplant implant: MacroBombImplant
- type: entity - type: entity
id: DeathRattleImplanter id: DeathRattleImplanter
name: death rattle implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: death rattle
components: components:
- type: Implanter - type: Implanter
implant: DeathRattleImplant implant: DeathRattleImplant
- type: entity - type: entity
id: DeathAcidifierImplanter id: DeathAcidifierImplanter
name: death acidifier implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: death acidifier
components: components:
- type: Implanter - type: Implanter
implant: DeathAcidifierImplant implant: DeathAcidifierImplant
@@ -245,8 +245,8 @@
- type: entity - type: entity
id: MindShieldImplanter id: MindShieldImplanter
name: mind-shield implanter
parent: BaseImplantOnlyImplanter parent: BaseImplantOnlyImplanter
suffix: mind-shield
components: components:
- type: Implanter - type: Implanter
implant: MindShieldImplant implant: MindShieldImplant

View File

@@ -204,3 +204,13 @@
Telecrystal: 1 Telecrystal: 1
categories: categories:
- UplinkAmmo - UplinkAmmo
- type: listing
id: UplinkMindSlaveImplanter
name: uplink-mind-slave
description: uplink-mind-slave-desc
productEntity: MindSlaveImplanter
cost:
Telecrystal: 6
categories:
- UplinkImplants

View File

@@ -1,15 +1,23 @@
- type: entity - type: entity
id: SmokeImplanter id: SmokeImplanter
name: имплант дыма
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: smoke
components: components:
- type: Implanter - type: Implanter
implant: SmokeImplant implant: SmokeImplant
- type: entity - type: entity
id: HardlightSpearImplanter id: HardlightSpearImplanter
name: hardlight spear implanter
parent: BaseImplantOnlyImplanterSyndi parent: BaseImplantOnlyImplanterSyndi
suffix: hardlight spear
components: components:
- type: Implanter - type: Implanter
implant: HardlightSpearImplant implant: HardlightSpearImplant
- type: entity
id: MindSlaveImplanter
parent: BaseImplantOnlyImplanterSyndi
suffix: mindslave
components:
- type: Implanter
implant: MindslaveImplant

View File

@@ -23,3 +23,16 @@
components: components:
- type: SubdermalImplant - type: SubdermalImplant
implantAction: ActivateHardlightSpearImplant 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

View File

@@ -51,3 +51,6 @@
- type: Tag - type: Tag
id: WeldedKnife id: WeldedKnife
- type: Tag
id: MindSlave

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

View File

@@ -0,0 +1,17 @@
{
"version": 1,
"size": {
"x": 32,
"y": 32
},
"license": "CC-BY-SA-3.0",
"copyright": "@JustNemo",
"states": [
{
"name": "slave"
},
{
"name": "master"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B