diff --git a/Content.Server/DeltaV/Implants/SubdermalBionicSyrinxImplantSystem.cs b/Content.Server/DeltaV/Implants/SubdermalBionicSyrinxImplantSystem.cs index 30a894a2d1..96adfc2ab2 100644 --- a/Content.Server/DeltaV/Implants/SubdermalBionicSyrinxImplantSystem.cs +++ b/Content.Server/DeltaV/Implants/SubdermalBionicSyrinxImplantSystem.cs @@ -29,7 +29,7 @@ public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnInsert); + SubscribeLocalEvent(OnInsert); // WD EDIT SubscribeLocalEvent(OnSpeakerNameTransform); SubscribeLocalEvent(OnChangeName); // We need to remove the SyrinxVoiceMaskComponent from the owner before the implant @@ -37,16 +37,17 @@ public override void Initialize() SubscribeLocalEvent(OnRemove, before: new[] { typeof(SubdermalImplantSystem) }); } - private void OnInsert(EntityUid uid, VoiceMaskerComponent component, ImplantImplantedEvent args) + // WD EDIT START + private void OnInsert(EntityUid uid, VoiceMaskerComponent component, SubdermalImplantInserted args) { - if (!args.Implanted.HasValue || - !_tag.HasTag(args.Implant, BionicSyrinxImplant)) + if (_tag.HasTag(uid, BionicSyrinxImplant)) return; - var voicemask = EnsureComp(args.Implanted.Value); - voicemask.VoiceName = MetaData(args.Implanted.Value).EntityName; - Dirty(args.Implanted.Value, voicemask); + var voicemask = EnsureComp(args.Target); + voicemask.VoiceName = MetaData(args.Target).EntityName; + Dirty(args.Target, voicemask); } + // WD EDIT END private void OnRemove(EntityUid uid, VoiceMaskerComponent component, EntGotRemovedFromContainerMessage args) { diff --git a/Content.Server/Mindshield/MindShieldSystem.cs b/Content.Server/Mindshield/MindShieldSystem.cs deleted file mode 100644 index bfca6c008e..0000000000 --- a/Content.Server/Mindshield/MindShieldSystem.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Content.Server.Administration.Logs; -using Content.Server.Mind; -using Content.Server.Popups; -using Content.Server.Roles; -using Content.Shared.Database; -using Content.Shared.Implants; -using Content.Shared.Implants.Components; -using Content.Shared.Mindshield.Components; -using Content.Shared.Revolutionary.Components; -using Content.Shared.Tag; - -namespace Content.Server.Mindshield; - -/// -/// System used for checking if the implanted is a Rev or Head Rev. -/// -public sealed class MindShieldSystem : EntitySystem -{ - [Dependency] private readonly IAdminLogManager _adminLogManager = default!; - [Dependency] private readonly RoleSystem _roleSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; - [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; - - [ValidatePrototypeId] - public const string MindShieldTag = "MindShield"; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(ImplantCheck); - } - - /// - /// Checks if the implant was a mindshield or not - /// - public void ImplantCheck(EntityUid uid, SubdermalImplantComponent comp, ref ImplantImplantedEvent ev) - { - if (_tag.HasTag(ev.Implant, MindShieldTag) && ev.Implanted != null) - { - EnsureComp(ev.Implanted.Value); - MindShieldRemovalCheck(ev.Implanted.Value, ev.Implant); - } - } - - /// - /// Checks if the implanted person was a Rev or Head Rev and remove role or destroy mindshield respectively. - /// - public void MindShieldRemovalCheck(EntityUid implanted, EntityUid implant) - { - if (HasComp(implanted)) - { - _popupSystem.PopupEntity(Loc.GetString("head-rev-break-mindshield"), implanted); - QueueDel(implant); - return; - } - - if (_mindSystem.TryGetMind(implanted, out var mindId, out _) && - _roleSystem.MindTryRemoveRole(mindId)) - { - _adminLogManager.Add(LogType.Mind, LogImpact.Medium, $"{ToPrettyString(implanted)} was deconverted due to being implanted with a Mindshield."); - } - } -} diff --git a/Content.Server/_White/Implants/ImplantsSystem.cs b/Content.Server/_White/Implants/ImplantsSystem.cs new file mode 100644 index 0000000000..81123097c4 --- /dev/null +++ b/Content.Server/_White/Implants/ImplantsSystem.cs @@ -0,0 +1,76 @@ +using Content.Server.Administration.Logs; +using Content.Server.Mind; +using Content.Server.Popups; +using Content.Server.Roles; +using Content.Shared._White.Implants.NeuroStabilization; +using Content.Shared.Database; +using Content.Shared.Implants; +using Content.Shared.Implants.Components; +using Content.Shared.Mindshield.Components; +using Content.Shared.Revolutionary.Components; +using Content.Shared.Tag; + +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 TagSystem _tag = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + + [ValidatePrototypeId] + private const string MindShieldTag = "MindShield"; + + [ValidatePrototypeId] + private const string NeuroStabilizationTag = "NeuroStabilization"; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnImplantInserted); + SubscribeLocalEvent(OnImplantRemoved); + } + + private void OnImplantInserted(EntityUid uid, SubdermalImplantComponent component, SubdermalImplantInserted args) + { + if (_tag.HasTag(uid, MindShieldTag) + && RevolutionCheck(uid, args.Target)) + EnsureComp(args.Target); + + if (_tag.HasTag(uid, NeuroStabilizationTag)) + EnsureComp(args.Target); + } + + private void OnImplantRemoved(EntityUid uid, SubdermalImplantComponent component, SubdermalImplantRemoved args) + { + if (_tag.HasTag(uid, MindShieldTag)) + RemComp(args.Target); + + if (_tag.HasTag(uid, NeuroStabilizationTag)) + RemComp(args.Target); + } + + /// + /// 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) + { + if (HasComp(target)) + { + _popupSystem.PopupEntity(Loc.GetString("head-rev-break-mindshield"), target); + QueueDel(uid); + return false; + } + + if (_mindSystem.TryGetMind(target, out var mindId, out _) + && _roleSystem.MindTryRemoveRole(mindId)) + { + _adminLogManager.Add(LogType.Mind, LogImpact.Medium, + $"{ToPrettyString(target)} was deconverted due to being implanted with a Mindshield."); + } + + return true; + } +} diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index 36a31bac1d..dce599ef15 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -69,6 +69,8 @@ public void Implant(EntityUid user, EntityUid target, EntityUid implanter, Impla implantContainer.OccludesLight = false; _container.Insert(implant.Value, implantContainer); + RaiseLocalEvent(implant.Value, new SubdermalImplantInserted(user, target)); // WD EDIT + if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) DrawMode(implanter, component); else @@ -146,6 +148,8 @@ public void Draw(EntityUid implanter, EntityUid user, EntityUid target, Implante _container.Insert(implant, implanterContainer); permanentFound = implantComp.Permanent; + RaiseLocalEvent(implant, new SubdermalImplantRemoved(user, target)); // WD EDIT + var ev = new TransferDnaEvent { Donor = target, Recipient = implanter }; RaiseLocalEvent(target, ref ev); @@ -225,3 +229,31 @@ public AddImplantAttemptEvent(EntityUid user, EntityUid target, EntityUid implan Implanter = implanter; } } + +// WD EDIT START +public sealed class SubdermalImplantInserted(EntityUid user, EntityUid target) +{ + /// + /// Entity who implants + /// + public EntityUid User = user; + + /// + /// Entity being implanted + /// + public EntityUid Target = target; +} + +public sealed class SubdermalImplantRemoved(EntityUid user, EntityUid target) +{ + /// + /// Entity who removes implant + /// + public EntityUid User = user; + + /// + /// Entity which implant is removing + /// + public EntityUid Target = target; +} +// WD EDIT END diff --git a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs index 830d2270aa..0df552d8a6 100644 --- a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs +++ b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs @@ -53,9 +53,6 @@ private void OnInsert(EntityUid uid, SubdermalImplantComponent component, EntGot } } } - - var ev = new ImplantImplantedEvent(uid, component.ImplantedEntity.Value); - RaiseLocalEvent(uid, ref ev); } private void OnRemoveAttempt(EntityUid uid, SubdermalImplantComponent component, ContainerGettingRemovedAttemptEvent args) @@ -125,6 +122,8 @@ public void ForceImplant(EntityUid target, EntityUid implant, SubdermalImplantCo component.ImplantedEntity = target; _container.Insert(implant, implantContainer); + + RaiseLocalEvent(implant, new SubdermalImplantInserted(target, target)); // WD EDIT } /// @@ -185,23 +184,3 @@ public ImplantRelayEvent(T ev) Event = ev; } } - -/// -/// Event that is raised whenever someone is implanted with any given implant. -/// Raised on the the implant entity. -/// -/// -/// implant implant implant implant -/// -[ByRefEvent] -public readonly struct ImplantImplantedEvent -{ - public readonly EntityUid Implant; - public readonly EntityUid? Implanted; - - public ImplantImplantedEvent(EntityUid implant, EntityUid? implanted) - { - Implant = implant; - Implanted = implanted; - } -} diff --git a/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerComponent.cs b/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerComponent.cs new file mode 100644 index 0000000000..740f492946 --- /dev/null +++ b/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Shared._White.Implants.NeuroStabilization; + +[RegisterComponent] +public sealed partial class NeuroStabilizationComponent : Component +{ + [DataField] + public bool Electrocution = true; + + [DataField] + public TimeSpan TimeElectrocution = TimeSpan.FromSeconds(1); + + [DataField] + public float DamageModifier = 0.66f; +} diff --git a/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerSystem.cs b/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerSystem.cs new file mode 100644 index 0000000000..c0234c71f3 --- /dev/null +++ b/Content.Shared/_White/Implants/NeuroStabilization/NeuroStabilizerSystem.cs @@ -0,0 +1,28 @@ +using Content.Shared.Electrocution; +using Content.Shared.Damage.Systems; + +namespace Content.Shared._White.Implants.NeuroStabilization; + +public sealed class NeuroStabilizationSystem : EntitySystem +{ + [Dependency] private readonly SharedElectrocutionSystem _electrocution = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(BeforeStaminaDamage); + } + + private void BeforeStaminaDamage(EntityUid uid, NeuroStabilizationComponent component, ref BeforeStaminaDamageEvent args) + { + args.Cancelled = true; + + if (!component.Electrocution) + return; + + var damage = (int) MathF.Round(args.Value * component.DamageModifier); + _electrocution.TryDoElectrocution(uid, null, damage, component.TimeElectrocution, + false, 0.5f, null, true); + } +} diff --git a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl index ab0f38d679..38e64879eb 100644 --- a/Resources/Locale/en-US/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/_white/store/uplink-catalog.ftl @@ -10,6 +10,9 @@ uplink-betrayal-knife-desc = Syndicate teleporter, when used, moves 3-8 meters f uplink-ebow-name = Small energy crossbow uplink-ebow-desc = A fairly quiet weapon that automatically reloads and stuns. It goes well with other types of weapons. +uplink-neuro-control = Neuro stabilization implanter +uplink-neuro-control-desc = Blocks all of the incoming stamina damage while dealing shock damage instead. + uplink-implanter-name = Implanter uplink-implanter-desc = An advanced implant that allows you to quickly insert and remove implants. diff --git a/Resources/Locale/ru-RU/_white/implants/neurostabilization.ftl b/Resources/Locale/ru-RU/_white/implants/neurostabilization.ftl deleted file mode 100644 index d360d68476..0000000000 --- a/Resources/Locale/ru-RU/_white/implants/neurostabilization.ftl +++ /dev/null @@ -1,5 +0,0 @@ -uplink-neuro-stabilization = Имплант нейростабилизации -uplink-neuro-stabilization-desc = Блокирует весь входящий урон по выносливости, компенсируя его шоковым зарядом. - -ent-NeuroStabilizationImplant = Имплант нейростабилизации - .desc = Блокирует весь входящий урон по выносливости за счет шока. 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 ce7482cff8..788abf0a8a 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 @@ -1,3 +1,7 @@ +ent-NeuroStabilizationImplanter = { ent-BaseImplanter } + .desc = { ent-BaseImplanter.desc } + .suffix = нейро стабилизация + ent-ImplanterSyndi = { ent-BaseImplanter } .desc = Компактный одноразовый шприц, предназначенный исключительно для введения и извлечения подкожных имплантатов. 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 4ebb6a8da3..02d7d7bdf4 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 @@ -1,2 +1,5 @@ +ent-NeuroStabilizationImplant = имплант нейро стабализации + .desc = Блокирует весь входящий урон по выносливости за счет шока. + ent-SmokeImplant = имплант дыма - .desc = Этот имплант выпускает облако дыма при активации. \ No newline at end of file + .desc = Этот имплант выпускает облако дыма при активации. diff --git a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl index 8fa3f7b5d1..0149d91986 100644 --- a/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl +++ b/Resources/Locale/ru-RU/_white/store/uplink-catalog.ftl @@ -10,6 +10,9 @@ uplink-experimental-syndicate-teleporter-desc = Телепортер синди uplink-ebow-name = Маленький энергетический арбалет uplink-ebow-desc = Довольно тихое оружие, которое автоматически перезаряжается и оглушает. Хорошо сочетается с другими видами оружия. +uplink-neuro-control = Имплант нейро стабилизации +uplink-neuro-control-desc = Блокирует весь входящий урон по выносливости, компенсируя его шоковым зарядом, наносящим урон, пропорциональный заблокированному. + uplink-implanter-name = Имплантер uplink-implanter-desc = Продвинутый имплантер, позволяющий быстро вкалывать и вытаскивать импланты. diff --git a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml index 8434bf6484..b6648b3bd4 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml @@ -322,7 +322,6 @@ noSpawn: true components: - type: SubdermalImplant - permanent: true - type: Tag tags: - MindShield diff --git a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml index e29cf97d5c..fd6b69be96 100644 --- a/Resources/Prototypes/_White/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_White/Catalog/uplink_catalog.yml @@ -22,7 +22,6 @@ id: UplinkBetrayalKnife name: uplink-betrayal-knife-name description: uplink-betrayal-knife-desc - icon: { sprite: /Textures/_White/Objects/Weapons/Melee/Daggers/betrayal_knife.rsi, state: icon } productEntity: BetrayalKnife cost: Telecrystal: 10 @@ -39,7 +38,6 @@ id: UplinkMiniEbow name: uplink-ebow-name description: uplink-ebow-desc - icon: { sprite: /Textures/_White/Objects/Weapons/Guns/Battery/mini-ebow.rsi, state: icon } productEntity: EnergyCrossbowMini cost: Telecrystal: 10 @@ -52,6 +50,17 @@ - NukeOpsUplink saleLimit: 1 +- type: listing + id: NeuroControlImplanter + name: uplink-neuro-control + description: uplink-neuro-control-desc + icon: { sprite: /Textures/Interface/Alerts/stamina.rsi, state: stamina5 } + productEntity: NeuroStabilizationImplanter + cost: + Telecrystal: 2 + categories: + - UplinkImplants + - type: listing id: UplinkImplanterSyndi name: uplink-implanter-name diff --git a/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml b/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml index 99c0e1aa96..43d1bbd593 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Misc/implanters.yml @@ -1,3 +1,11 @@ +- type: entity + parent: BaseImplantOnlyImplanterSyndi + id: NeuroStabilizationImplanter + suffix: neuro stabilization + components: + - type: Implanter + implant: NeuroStabilizationImplant + - type: entity parent: Implanter id: ImplanterSyndi diff --git a/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml index 9813f190a4..1a727e98ad 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/_White/Entities/Objects/Misc/subdermal_implants.yml @@ -1,3 +1,15 @@ +- type: entity + parent: BaseSubdermalImplant + id: NeuroStabilizationImplant + name: neuro stabilization implant + description: Blocks all of the incoming stamina damage at the cost of frying you nerve system a bit each time. + noSpawn: true + components: + - type: SubdermalImplant + - type: Tag + tags: + - NeuroStabilization + - type: entity parent: BaseSubdermalImplant id: SmokeImplant @@ -12,4 +24,4 @@ spreadAmount: 25 duration: 15 - type: SoundOnTrigger - sound: /Audio/Effects/smoke.ogg \ No newline at end of file + sound: /Audio/Effects/smoke.ogg diff --git a/Resources/Prototypes/_White/tags.yml b/Resources/Prototypes/_White/tags.yml index 62e70f42a9..fe2392f438 100644 --- a/Resources/Prototypes/_White/tags.yml +++ b/Resources/Prototypes/_White/tags.yml @@ -1,2 +1,5 @@ - type: Tag - id: EnergySword \ No newline at end of file + id: EnergySword + +- type: Tag + id: NeuroStabilization \ No newline at end of file