base.Initialize();
SubscribeLocalEvent<MindShieldComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
+ SubscribeLocalEvent<FakeMindShieldComponent, GetStatusIconsEvent>(OnGetStatusIconsEventFake);
+ }
+ // TODO: Probably need to get this OFF of client since this can be read by bad actors rather easily
+ // ...imagine cheating in a game about silly paper dolls
+ private void OnGetStatusIconsEventFake(EntityUid uid, FakeMindShieldComponent component, ref GetStatusIconsEvent ev)
+ {
+ if(!IsActive)
+ return;
+ if (component.IsEnabled && _prototype.TryIndex(component.MindShieldStatusIcon, out var fakeStatusIconPrototype))
+ ev.StatusIcons.Add(fakeStatusIconPrototype);
}
private void OnGetStatusIconsEvent(EntityUid uid, MindShieldComponent component, ref GetStatusIconsEvent ev)
return;
}
- // Check if we are trying to implant a implant which is already implanted
- if (implant.HasValue && !component.AllowMultipleImplants && CheckSameImplant(target, implant.Value))
- {
- var name = Identity.Name(target, EntityManager, args.User);
- var msg = Loc.GetString("implanter-component-implant-already", ("implant", implant), ("target", name));
- _popup.PopupEntity(msg, target, args.User);
- args.Handled = true;
- return;
- }
-
-
//Implant self instantly, otherwise try to inject the target.
if (args.User == target)
Implant(target, target, uid, component);
args.Handled = true;
}
- public bool CheckSameImplant(EntityUid target, EntityUid implant)
- {
- if (!TryComp<ImplantedComponent>(target, out var implanted))
- return false;
- var implantPrototype = Prototype(implant);
- return implanted.ImplantContainer.ContainedEntities.Any(entity => Prototype(entity) == implantPrototype);
- }
/// <summary>
/// Attempt to implant someone else.
args.PushMarkup(Loc.GetString("implanter-contained-implant-text", ("desc", component.ImplantData.Item2)));
}
+ public bool CheckSameImplant(EntityUid target, EntityUid implant)
+ {
+ if (!TryComp<ImplantedComponent>(target, out var implanted))
+ return false;
+ var implantPrototype = Prototype(implant);
+ return implanted.ImplantContainer.ContainedEntities.Any(entity => Prototype(entity) == implantPrototype);
+ }
//Instantly implant something and add all necessary components and containers.
//Set to draw mode if not implant only
public void Implant(EntityUid user, EntityUid target, EntityUid implanter, ImplanterComponent component)
if (!CanImplant(user, target, implanter, component, out var implant, out var implantComp))
return;
+ // Check if we are trying to implant a implant which is already implanted
+ // Check AFTER the doafter to prevent "is it a fake?" metagaming against deceptive implants
+ if (!component.AllowMultipleImplants && CheckSameImplant(target, implant.Value))
+ {
+ var name = Identity.Name(target, EntityManager, user);
+ var msg = Loc.GetString("implanter-component-implant-already", ("implant", implant), ("target", name));
+ _popup.PopupEntity(msg, target, user);
+ return;
+ }
+
//If the target doesn't have the implanted component, add it.
var implantedComp = EnsureComp<ImplantedComponent>(target);
var implantContainer = implantedComp.ImplantContainer;
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Mindshield.Components;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class FakeMindShieldImplantComponent : Component
+{
+}
--- /dev/null
+using Content.Shared.StatusIcon;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Mindshield.Components;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class FakeMindShieldComponent : Component
+{
+
+ /// <summary>
+ /// The state of the Fake mindshield, if true the owning entity will display a mindshield effect on their job icon
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public bool IsEnabled { get; set; } = false;
+
+ /// <summary>
+ /// The Security status icon displayed to the security officer. Should be a duplicate of the one the mindshield uses since it's spoofing that
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public ProtoId<SecurityIconPrototype> MindShieldStatusIcon = "MindShieldIcon";
+}
--- /dev/null
+using Content.Shared.Actions;
+using Content.Shared.Implants;
+using Content.Shared.Implants.Components;
+using Content.Shared.Mindshield.Components;
+
+namespace Content.Shared.Mindshield.FakeMindShield;
+
+public sealed class SharedFakeMindShieldImplantSystem : EntitySystem
+{
+ [Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent<SubdermalImplantComponent, FakeMindShieldToggleEvent>(OnFakeMindShieldToggle);
+ SubscribeLocalEvent<FakeMindShieldImplantComponent, ImplantImplantedEvent>(ImplantCheck);
+ }
+ /// <summary>
+ /// Raise the Action of a Implanted user toggling their implant to the FakeMindshieldComponent on their entity
+ /// </summary>
+ private void OnFakeMindShieldToggle(Entity<SubdermalImplantComponent> entity, ref FakeMindShieldToggleEvent ev)
+ {
+ ev.Handled = true;
+ if (entity.Comp.ImplantedEntity is not { } ent)
+ return;
+
+ if (!TryComp<FakeMindShieldComponent>(ent, out var comp))
+ return;
+ _actionsSystem.SetToggled(ev.Action, !comp.IsEnabled); // Set it to what the Mindshield component WILL be after this
+ RaiseLocalEvent(ent, ev); //this reraises the action event to support an eventual future Changeling Antag which will also be using this component for it's "mindshield" ability
+ }
+ private void ImplantCheck(EntityUid uid, FakeMindShieldImplantComponent component ,ref ImplantImplantedEvent ev)
+ {
+ if (ev.Implanted != null)
+ EnsureComp<FakeMindShieldComponent>(ev.Implanted.Value);
+ }
+}
--- /dev/null
+using Content.Shared.Actions;
+using Content.Shared.Mindshield.Components;
+
+namespace Content.Shared.Mindshield.FakeMindShield;
+
+public sealed class SharedFakeMindShieldSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent<FakeMindShieldComponent, FakeMindShieldToggleEvent>(OnToggleMindshield);
+ }
+
+ private void OnToggleMindshield(EntityUid uid, FakeMindShieldComponent comp, FakeMindShieldToggleEvent toggleEvent)
+ {
+ comp.IsEnabled = !comp.IsEnabled;
+ Dirty(uid, comp);
+ }
+}
+
+public sealed partial class FakeMindShieldToggleEvent : InstantActionEvent;
implanter-contained-implant-text = [color=green]{$desc}[/color]
+action-name-toggle-fake-mindshield = [color=green]Toggle Fake Mindshield[/color]
+action-description-toggle-fake-mindshield = Turn the Fake Mindshield implants transmission on/off
+
## Implant Popups
scramble-implant-activated-popup = Your appearance shifts and changes!
uplink-business-card-name = Syndicate Business Card
uplink-business-card-desc = A business card that you can give to someone to demonstrate your involvement in the syndicate or leave at the crime scene in order to make fun of the detective. You can buy no more than three of them.
+
+uplink-fake-mindshield-name = Fake Mindshield
+uplink-fake-mindshield-desc = A togglable implant capable of mimicking the same transmissions a real mindshield puts out when on, tricking capable Heads-up displays into thinking you have a mindshield (Nanotrasen brand implanter not provided.)
itemIconStyle: NoItem
useDelay: 1 # emote spam
event: !type:ToggleActionEvent
+
+- type: entity
+ id: FakeMindShieldToggleAction
+ name: action-name-toggle-fake-mindshield
+ description: action-description-toggle-fake-mindshield
+ components:
+ - type: InstantAction
+ icon: { sprite: Interface/Actions/actions_fakemindshield.rsi, state: icon }
+ iconOn: { sprite: Interface/Actions/actions_fakemindshield.rsi, state: icon-on }
+ itemIconStyle: NoItem
+ useDelay: 1
+ event: !type:FakeMindShieldToggleEvent
- ClothingShoesChameleon
- BarberScissors
- ChameleonProjector
+ - FakeMindShieldImplanter
- AgentIDCard
- type: thiefBackpackSet
components:
- SurplusBundle
+- type: listing
+ id: UplinkFakeMindshield
+ name: uplink-fake-mindshield-name
+ description: uplink-fake-mindshield-desc
+ icon: { sprite: Interface/Actions/actions_fakemindshield.rsi, state: icon-on }
+ productEntity: FakeMindShieldImplanter
+ discountDownTo:
+ Telecrystal: 2
+ cost:
+ Telecrystal: 4
+ categories:
+ - UplinkImplants
+
+
# Wearables
- type: listing
- type: Implanter
implant: DeathAcidifierImplant
+- type: entity
+ id: FakeMindShieldImplanter
+ suffix: fake mindshield
+ parent: BaseImplantOnlyImplanterSyndi
+ components:
+ - type: Implanter
+ implant: FakeMindShieldImplant
+
# Security and Command implanters
- type: entity
- Dead
- type: Rattle
+- type: entity
+ parent: BaseSubdermalImplant
+ id: FakeMindShieldImplant
+ name: fake mindshield implant
+ description: This implant allows the implanter to produce a fake signal that NT security huds use to identify individuals implanted with a mindshield.
+ categories: [ HideSpawnMenu ]
+ components:
+ - type: SubdermalImplant
+ implantAction: FakeMindShieldToggleAction
+ - type: FakeMindShieldImplant
+
# Sec and Command implants
- type: entity
--- /dev/null
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by Ubaser (Discord) for SS14, Modified for purpose by brassicaprime69 (Discord)",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "icon-on"
+ }
+ ]
+}