Skip to content

Commit

Permalink
Fake mindshield componentry and Implanter (#34079)
Browse files Browse the repository at this point in the history
* Fake Mindshield (With some bad sprites)

- Add FakeMindshield System and Component

- Add FakeMindsheildImplantSystem and Component

- modify ShowMindShieldIconsSystem to check for FakeMindshields

- add all supporting yaml for the Implants, action and uplink

- add loc file stuff

- add unfinished sprites

* Cleanup, add to thief toolbox, remove metagame

- Move Implant sameness check to AFTER the implant DoAfter
to prevent instant identification of Deception Implants

- cleanup the systems and components

- add the fake mindshield to the Thief toolbox

* part 1 of fixing the folder problem

* Make the fakemindshield sprite folder lowercase

* CR - Move ImplantCheck into shared, cleanup

- Moved ImplantCheck and eventsubscription into Shared

- Remove Client/Server extensions of FakeMindshieldImplantSystem and
FakeMindShieldSystem and make shared Sealed

- make OnToggleMindshield Private, use the event!

* CR - Cleanup extra lines, fix some Prototype

- cleaned up extra liens in ImplanterSystem and
SharedFakeMindshieldSystem from when i was developing

- Uplink catalog no longer lists the implant in 2 spots,
only implants now, also uses the On state action icon

- added a comment about why it's reraising the action event
rather than directly interacting with the FakeMindshield Component

* Fake Mindshield CR:

- Added a comment about IsEnabled

- moved OnFakeMindShieldToggle to Entity<> from Uid, Comp

- fixed some formatting in uplink_catalog

* CR - Add a bit more comment
  • Loading branch information
poklj authored Jan 28, 2025
1 parent c212273 commit c504588
Show file tree
Hide file tree
Showing 17 changed files with 183 additions and 18 deletions.
10 changes: 10 additions & 0 deletions Content.Client/Overlays/ShowMindShieldIconsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ public override void Initialize()
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)
Expand Down
18 changes: 0 additions & 18 deletions Content.Server/Implants/ImplanterSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,6 @@ private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent componen
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);
Expand All @@ -79,14 +68,7 @@ private void OnImplanterAfterInteract(EntityUid uid, ImplanterComponent componen
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.
Expand Down
17 changes: 17 additions & 0 deletions Content.Shared/Implants/SharedImplanterSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,31 @@ private void OnExamine(EntityUid uid, ImplanterComponent component, ExaminedEven

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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Robust.Shared.GameStates;

namespace Content.Shared.Mindshield.Components;

[RegisterComponent, NetworkedComponent]
public sealed partial class FakeMindShieldImplantComponent : Component
{
}
22 changes: 22 additions & 0 deletions Content.Shared/Mindshield/Components/FakeMindshieldComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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;
3 changes: 3 additions & 0 deletions Resources/Locale/en-US/implant/implant.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ implanter-label = [color=green]{$implantName}[/color]
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!
Expand Down
3 changes: 3 additions & 0 deletions Resources/Locale/en-US/store/uplink-catalog.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,6 @@ uplink-combat-bakery-desc = A kit of clandestine baked weapons. Contains a bague
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.)
12 changes: 12 additions & 0 deletions Resources/Prototypes/Actions/types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,15 @@
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
1 change: 1 addition & 0 deletions Resources/Prototypes/Catalog/thief_toolbox_sets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- ClothingShoesChameleon
- BarberScissors
- ChameleonProjector
- FakeMindShieldImplanter
- AgentIDCard

- type: thiefBackpackSet
Expand Down
14 changes: 14 additions & 0 deletions Resources/Prototypes/Catalog/uplink_catalog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,20 @@
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
Expand Down
8 changes: 8 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/implanters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@
- type: Implanter
implant: DeathAcidifierImplant

- type: entity
id: FakeMindShieldImplanter
suffix: fake mindshield
parent: BaseImplantOnlyImplanterSyndi
components:
- type: Implanter
implant: FakeMindShieldImplant

# Security and Command implanters

- type: entity
Expand Down
11 changes: 11 additions & 0 deletions Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,17 @@
- 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
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"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"
}
]
}

0 comments on commit c504588

Please sign in to comment.