]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Syndicate Reinforcement Specializations: Medic, Spy, Thief (#29853)
authorPlykiya <58439124+Plykiya@users.noreply.github.com>
Sun, 21 Jul 2024 10:32:25 +0000 (03:32 -0700)
committerGitHub <noreply@github.com>
Sun, 21 Jul 2024 10:32:25 +0000 (20:32 +1000)
* Syndicate thief, spy, medic

* Fixes description for nukies

* update description for uplink

* Implement the radial menu

* forgot these were necessary to push lol

---------

Co-authored-by: plykiya <plykiya@protonmail.com>
16 files changed:
Content.Client/Ghost/GhostRoleRadioBoundUserInterface.cs [new file with mode: 0644]
Content.Client/Ghost/GhostRoleRadioMenu.xaml [new file with mode: 0644]
Content.Client/Ghost/GhostRoleRadioMenu.xaml.cs [new file with mode: 0644]
Content.Server/Bible/BibleSystem.cs
Content.Server/Ghost/Roles/GhostRoleSystem.cs
Content.Server/Zombies/ZombieSystem.Transform.cs
Content.Shared/Ghost/GhostRoleRadioEvents.cs [new file with mode: 0644]
Content.Shared/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs [moved from Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs with 85% similarity]
Content.Shared/Ghost/Roles/GhostRolePrototype.cs
Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
Resources/Locale/en-US/store/uplink-catalog.ftl
Resources/Prototypes/Catalog/uplink_catalog.yml
Resources/Prototypes/Entities/Mobs/Player/human.yml
Resources/Prototypes/Entities/Objects/Devices/Syndicate_Gadgets/reinforcement_teleporter.yml
Resources/Prototypes/Roles/Antags/traitor.yml
Resources/Prototypes/Roles/Ghostroles/syndicate.yml

diff --git a/Content.Client/Ghost/GhostRoleRadioBoundUserInterface.cs b/Content.Client/Ghost/GhostRoleRadioBoundUserInterface.cs
new file mode 100644 (file)
index 0000000..3394497
--- /dev/null
@@ -0,0 +1,29 @@
+using Content.Shared.Ghost.Roles;
+using Robust.Client.UserInterface;
+using Robust.Shared.Prototypes;
+
+namespace Content.Client.Ghost;
+
+public sealed class GhostRoleRadioBoundUserInterface : BoundUserInterface
+{
+    private GhostRoleRadioMenu? _ghostRoleRadioMenu;
+
+    public GhostRoleRadioBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+    {
+        IoCManager.InjectDependencies(this);
+    }
+
+    protected override void Open()
+    {
+        base.Open();
+
+        _ghostRoleRadioMenu = this.CreateWindow<GhostRoleRadioMenu>();
+        _ghostRoleRadioMenu.SetEntity(Owner);
+        _ghostRoleRadioMenu.SendGhostRoleRadioMessageAction += SendGhostRoleRadioMessage;
+    }
+
+    public void SendGhostRoleRadioMessage(ProtoId<GhostRolePrototype> protoId)
+    {
+        SendMessage(new GhostRoleRadioMessage(protoId));
+    }
+}
diff --git a/Content.Client/Ghost/GhostRoleRadioMenu.xaml b/Content.Client/Ghost/GhostRoleRadioMenu.xaml
new file mode 100644 (file)
index 0000000..c35ee12
--- /dev/null
@@ -0,0 +1,8 @@
+<ui:RadialMenu
+    xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
+    CloseButtonStyleClass="RadialMenuCloseButton"
+    VerticalExpand="True"
+    HorizontalExpand="True">
+    <ui:RadialContainer Name="Main">
+    </ui:RadialContainer>
+</ui:RadialMenu>
diff --git a/Content.Client/Ghost/GhostRoleRadioMenu.xaml.cs b/Content.Client/Ghost/GhostRoleRadioMenu.xaml.cs
new file mode 100644 (file)
index 0000000..b05ac3f
--- /dev/null
@@ -0,0 +1,107 @@
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Ghost.Roles;
+using Content.Shared.Ghost.Roles.Components;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Prototypes;
+using System.Numerics;
+
+namespace Content.Client.Ghost;
+
+public sealed partial class GhostRoleRadioMenu : RadialMenu
+{
+    [Dependency] private readonly EntityManager _entityManager = default!;
+    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
+    public event Action<ProtoId<GhostRolePrototype>>? SendGhostRoleRadioMessageAction;
+
+    public EntityUid Entity { get; set; }
+
+    public GhostRoleRadioMenu()
+    {
+        IoCManager.InjectDependencies(this);
+        RobustXamlLoader.Load(this);
+    }
+
+    public void SetEntity(EntityUid uid)
+    {
+        Entity = uid;
+        RefreshUI();
+    }
+
+    private void RefreshUI()
+    {
+        // The main control that will contain all of the clickable options
+        var main = FindControl<RadialContainer>("Main");
+
+        // The purpose of this radial UI is for ghost role radios that allow you to select
+        // more than one potential option, such as with kobolds/lizards.
+        // This means that it won't show anything if SelectablePrototypes is empty.
+        if (!_entityManager.TryGetComponent<GhostRoleMobSpawnerComponent>(Entity, out var comp))
+            return;
+
+        foreach (var ghostRoleProtoString in comp.SelectablePrototypes)
+        {
+            // For each prototype we find we want to create a button that uses the name of the ghost role
+            // as the hover tooltip, and the icon is taken from either the ghost role entityprototype
+            // or the indicated icon entityprototype.
+            if (!_prototypeManager.TryIndex<GhostRolePrototype>(ghostRoleProtoString, out var ghostRoleProto))
+                continue;
+
+            var button = new GhostRoleRadioMenuButton()
+            {
+                StyleClasses = { "RadialMenuButton" },
+                SetSize = new Vector2(64, 64),
+                ToolTip = Loc.GetString(ghostRoleProto.Name),
+                ProtoId = ghostRoleProto.ID,
+            };
+
+            var entProtoView = new EntityPrototypeView()
+            {
+                SetSize = new Vector2(48, 48),
+                VerticalAlignment = VAlignment.Center,
+                HorizontalAlignment = HAlignment.Center,
+                Stretch = SpriteView.StretchMode.Fill
+            };
+
+            // pick the icon if it exists, otherwise fallback to the ghost role's entity
+            if (_prototypeManager.TryIndex(ghostRoleProto.IconPrototype, out var iconProto))
+                entProtoView.SetPrototype(iconProto);
+            else
+                entProtoView.SetPrototype(comp.Prototype);
+
+            button.AddChild(entProtoView);
+            main.AddChild(button);
+            AddGhostRoleRadioMenuButtonOnClickActions(main);
+        }
+    }
+
+    private void AddGhostRoleRadioMenuButtonOnClickActions(Control control)
+    {
+        var mainControl = control as RadialContainer;
+
+        if (mainControl == null)
+            return;
+
+        foreach (var child in mainControl.Children)
+        {
+            var castChild = child as GhostRoleRadioMenuButton;
+
+            if (castChild == null)
+                continue;
+
+            castChild.OnButtonUp += _ =>
+            {
+                SendGhostRoleRadioMessageAction?.Invoke(castChild.ProtoId);
+                Close();
+            };
+        }
+    }
+}
+
+public sealed class GhostRoleRadioMenuButton : RadialMenuTextureButton
+{
+    public ProtoId<GhostRolePrototype> ProtoId { get; set; }
+}
index 2cb0ac1dd76e015f369380fa956fc2e20d523a5d..76efe3290bf0c03fd18f07d7ba3722ee376c1f39 100644 (file)
@@ -1,11 +1,11 @@
 using Content.Server.Bible.Components;
-using Content.Server.Ghost.Roles.Components;
 using Content.Server.Ghost.Roles.Events;
 using Content.Server.Popups;
 using Content.Shared.ActionBlocker;
 using Content.Shared.Actions;
 using Content.Shared.Bible;
 using Content.Shared.Damage;
+using Content.Shared.Ghost.Roles.Components;
 using Content.Shared.IdentityManagement;
 using Content.Shared.Interaction;
 using Content.Shared.Inventory;
index b6627f11540fecbe3181de13bb4f4776d906c6d1..8b8aa7b8c8fcc8163a22d43c94e8ff8fd6bbf33f 100644 (file)
@@ -3,7 +3,6 @@ using Content.Server.Administration.Logs;
 using Content.Server.EUI;
 using Content.Server.Ghost.Roles.Components;
 using Content.Server.Ghost.Roles.Events;
-using Content.Server.Ghost.Roles.Raffles;
 using Content.Shared.Ghost.Roles.Raffles;
 using Content.Server.Ghost.Roles.UI;
 using Content.Server.Mind.Commands;
@@ -31,6 +30,7 @@ using Robust.Shared.Utility;
 using Content.Server.Popups;
 using Content.Shared.Verbs;
 using Robust.Shared.Collections;
+using Content.Shared.Ghost.Roles.Components;
 
 namespace Content.Server.Ghost.Roles
 {
@@ -80,6 +80,7 @@ namespace Content.Server.Ghost.Roles
             SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
             SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
             SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
+            SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
             _playerManager.PlayerStatusChanged += PlayerStatusChanged;
         }
 
@@ -786,6 +787,21 @@ namespace Content.Server.Ghost.Roles
                 _popupSystem.PopupEntity(msg, uid, userUid.Value);
             }
         }
+
+        public void OnGhostRoleRadioMessage(Entity<GhostRoleMobSpawnerComponent> entity, ref GhostRoleRadioMessage args)
+        {
+            if (!_prototype.TryIndex(args.ProtoId, out var ghostRoleProto))
+                return;
+
+            // if the prototype chosen isn't actually part of the selectable options, ignore it
+            foreach (var selectableProto in entity.Comp.SelectablePrototypes)
+            {
+                if (selectableProto == ghostRoleProto.EntityPrototype.Id)
+                    return;
+            }
+
+            SetMode(entity.Owner, ghostRoleProto, ghostRoleProto.Name, entity.Comp);
+        }
     }
 
     [AnyCommand]
index a8952009e66eac3bba63248a68cfac5ce2494ce8..74adea6cd6972a15968866e9cbc1918c7108d861 100644 (file)
@@ -9,7 +9,6 @@ using Content.Server.Inventory;
 using Content.Server.Mind;
 using Content.Server.Mind.Commands;
 using Content.Server.NPC;
-using Content.Server.NPC.Components;
 using Content.Server.NPC.HTN;
 using Content.Server.NPC.Systems;
 using Content.Server.Roles;
@@ -24,10 +23,8 @@ using Content.Shared.Humanoid;
 using Content.Shared.Interaction.Components;
 using Content.Shared.Mobs;
 using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
 using Content.Shared.Movement.Pulling.Components;
 using Content.Shared.Movement.Systems;
-using Content.Shared.NPC.Components;
 using Content.Shared.NPC.Systems;
 using Content.Shared.Nutrition.AnimalHusbandry;
 using Content.Shared.Nutrition.Components;
@@ -38,6 +35,7 @@ using Content.Shared.Zombies;
 using Content.Shared.Prying.Components;
 using Content.Shared.Traits.Assorted;
 using Robust.Shared.Audio.Systems;
+using Content.Shared.Ghost.Roles.Components;
 
 namespace Content.Server.Zombies
 {
diff --git a/Content.Shared/Ghost/GhostRoleRadioEvents.cs b/Content.Shared/Ghost/GhostRoleRadioEvents.cs
new file mode 100644 (file)
index 0000000..8bdd6e5
--- /dev/null
@@ -0,0 +1,21 @@
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Ghost.Roles;
+
+[Serializable, NetSerializable]
+public sealed class GhostRoleRadioMessage : BoundUserInterfaceMessage
+{
+    public ProtoId<GhostRolePrototype> ProtoId;
+
+    public GhostRoleRadioMessage(ProtoId<GhostRolePrototype> protoId)
+    {
+        ProtoId = protoId;
+    }
+}
+
+[Serializable, NetSerializable]
+public enum GhostRoleRadioUiKey : byte
+{
+    Key
+}
similarity index 85%
rename from Content.Server/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs
rename to Content.Shared/Ghost/Roles/Components/GhostRoleMobSpawnerComponent.cs
index 6116173f904bfab4c1915f06c452c93f01d236af..2e44effad96542061ee623856844ca1d0ea8db78 100644 (file)
@@ -1,12 +1,11 @@
-using Robust.Shared.Prototypes;
+using Robust.Shared.Prototypes;
 
-namespace Content.Server.Ghost.Roles.Components
+namespace Content.Shared.Ghost.Roles.Components
 {
     /// <summary>
     ///     Allows a ghost to take this role, spawning a new entity.
     /// </summary>
     [RegisterComponent, EntityCategory("Spawner")]
-    [Access(typeof(GhostRoleSystem))]
     public sealed partial class GhostRoleMobSpawnerComponent : Component
     {
         [DataField]
index bc36774ea8baca445867f91091e4a3f494e1daf1..3e81b5e46e8ed1509351683077c60e9450dc8265 100644 (file)
@@ -30,6 +30,13 @@ public sealed partial class GhostRolePrototype : IPrototype
     [DataField(required: true)]
     public EntProtoId EntityPrototype;
 
+    /// <summary>
+    /// The entity prototype's sprite to use to represent the ghost role
+    /// Use this if you don't want to use the entity itself
+    /// </summary>
+    [DataField]
+    public EntProtoId? IconPrototype = null;
+
     /// <summary>
     ///     Rules of the ghostrole
     /// </summary>
index 98f31e0ab074f59397a6cc6b477adc840972c244..b2082f772805222475001e77751d8a6b1c6e2c66 100644 (file)
@@ -197,6 +197,16 @@ ghost-role-information-syndicate-reinforcement-name = Syndicate Agent
 ghost-role-information-syndicate-reinforcement-description = Someone needs reinforcements. You, the first person the syndicate could find, will help them.
 ghost-role-information-syndicate-reinforcement-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with the agent who summoned you.
 
+ghost-role-information-syndicate-reinforcement-medic-name = Syndicate Medic
+ghost-role-information-syndicate-reinforcement-medic-description = Someone needs reinforcements. Your task is to keep the agent who called you alive.
+
+ghost-role-information-syndicate-reinforcement-spy-name = Syndicate Spy
+ghost-role-information-syndicate-reinforcement-spy-description = Someone needs reinforcements. Your speciality lies in espionage, do not be discovered.
+
+ghost-role-information-syndicate-reinforcement-thief-name = Syndicate Thief
+ghost-role-information-syndicate-reinforcement-thief-description = Someone needs reinforcements. Your job is to break in and retrieve something valuable for your agent.
+
+
 ghost-role-information-syndicate-monkey-reinforcement-name = Syndicate Monkey Agent
 ghost-role-information-syndicate-monkey-reinforcement-description = Someone needs reinforcements. You, a trained monkey, will help them.
 ghost-role-information-syndicate-monkey-reinforcement-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with the agent who summoned you.
index 8edbde9bdc9d7da7015543a01410ef204521ca1c..85a64c71ae183c6984c92ef9b93806c4a8949577 100644 (file)
@@ -124,8 +124,10 @@ uplink-black-jetpack-desc = A black jetpack. It allows you to fly around in spac
 uplink-reinforcement-radio-ancestor-name = Genetic Ancestor Reinforcement Teleporter
 uplink-reinforcement-radio-ancestor-desc =  Call in a trained ancestor of your choosing to assist you. Comes with a single syndicate cigarette.
 
+
 uplink-reinforcement-radio-name = Reinforcement Teleporter
-uplink-reinforcement-radio-desc =  Radio in a reinforcement agent of extremely questionable quality. No off button, buy this if you're ready to party. They have a pistol with no reserve ammo, and a knife. That's it.
+uplink-reinforcement-radio-traitor-desc =  Radio in a reinforcement agent of extremely questionable quality. No off button, buy this if you're ready to party. Call in a medic or spy or thief to help you out. Good luck.
+uplink-reinforcement-radio-nukeops-desc =  Radio in a reinforcement agent of extremely questionable quality. No off button, buy this if you're ready to party. They have a pistol with no reserve ammo, and a knife. That's it.
 
 uplink-reinforcement-radio-cyborg-assault-name = Syndicate Assault Cyborg Teleporter
 uplink-reinforcement-radio-cyborg-assault-desc =  A lean, mean killing machine with access to an Energy Sword, LMG, Cryptographic Sequencer, and a Pinpointer.
index 420982dcaecdea07de031b34d8e86675d2ea2ab8..fe8b038dd924f7a4704f3cfe03434c7da3595d1e 100644 (file)
 - type: listing
   id: UplinkReinforcementRadioSyndicate
   name: uplink-reinforcement-radio-name
-  description: uplink-reinforcement-radio-desc
+  description: uplink-reinforcement-radio-traitor-desc
   productEntity: ReinforcementRadioSyndicate
   icon: { sprite: Objects/Devices/communication.rsi, state: old-radio-urist }
   cost:
 - type: listing
   id: UplinkReinforcementRadioSyndicateNukeops # Version for Nukeops that spawns an agent with the NukeOperative component.
   name: uplink-reinforcement-radio-name
-  description: uplink-reinforcement-radio-desc
+  description: uplink-reinforcement-radio-nukeops-desc
   productEntity: ReinforcementRadioSyndicateNukeops
   icon: { sprite: Objects/Devices/communication.rsi, state: old-radio-urist }
   cost:
index cb0203ebe0e2e1a3f0c3d54da61737b203f71d9b..0b718746e13e90d916468b2e5a1f712ee5a2f0ee 100644 (file)
       giveUplink: false
       giveObjectives: false
 
+- type: entity
+  parent: MobHumanSyndicateAgent
+  id: MobHumanSyndicateAgentMedic
+  name: syndicate medic
+  components:
+  - type: Loadout
+    prototypes: [SyndicateReinforcementMedic]
+
+- type: entity
+  parent: MobHumanSyndicateAgent
+  id: MobHumanSyndicateAgentSpy
+  name: syndicate spy
+  components:
+  - type: Loadout
+    prototypes: [SyndicateReinforcementSpy]
+
+- type: entity
+  parent: MobHumanSyndicateAgent
+  id: MobHumanSyndicateAgentThief
+  name: syndicate thief
+  components:
+  - type: Loadout
+    prototypes: [SyndicateReinforcementThief]
+
 - type: entity
   parent: MobHumanSyndicateAgentBase
   id: MobHumanSyndicateAgentNukeops # Reinforcement exclusive to nukeops uplink
index d49c79f48b3c0a9e1deab6dd551168a550c83ab1..6aa2686fa6172390719cd279b88cddce39600d94 100644 (file)
@@ -1,6 +1,7 @@
 - type: entity
   parent: BaseItem
-  id: ReinforcementRadioSyndicate
+  abstract: true
+  id: ReinforcementRadio
   name: syndicate reinforcement radio
   description: Call in a syndicate agent of questionable quality, instantly! Only basic equipment provided.
   components:
@@ -8,29 +9,43 @@
     sprite: Objects/Devices/communication.rsi
     layers:
     - state: old-radio
+  - type: UserInterface
+    interfaces:
+      enum.GhostRoleRadioUiKey.Key:
+        type: GhostRoleRadioBoundUserInterface
+  - type: ActivatableUI
+    key: enum.GhostRoleRadioUiKey.Key
+
+- type: entity
+  parent: ReinforcementRadio
+  id: ReinforcementRadioSyndicate
+  name: syndicate reinforcement radio
+  description: Call in a syndicate agent of questionable quality, instantly!
+  components:
   - type: GhostRole
-    name: ghost-role-information-syndicate-reinforcement-name
+    name: ghost-role-information-syndicate-reinforcement-spy-name
     description: ghost-role-information-syndicate-reinforcement-description
     rules: ghost-role-information-syndicate-reinforcement-rules
     raffle:
       settings: default
   - type: GhostRoleMobSpawner
-    prototype: MobHumanSyndicateAgent
-  - type: EmitSoundOnUse
-    sound: /Audio/Effects/Emotes/parp1.ogg
-  - type: UseDelay
-    delay: 300
+    prototype: MobHumanSyndicateAgentSpy
+    selectablePrototypes: ["SyndicateAgentMedic", "SyndicateAgentSpy", "SyndicateAgentThief"]
 
 - type: entity
-  parent: ReinforcementRadioSyndicate
+  parent: ReinforcementRadio
   id: ReinforcementRadioSyndicateNukeops # Reinforcement radio exclusive to nukeops uplink
   suffix: NukeOps
   components:
+  - type: GhostRole
+    name: ghost-role-information-syndicate-reinforcement-name
+    description: ghost-role-information-syndicate-reinforcement-description
+    rules: ghost-role-information-syndicate-reinforcement-rules
   - type: GhostRoleMobSpawner
     prototype: MobHumanSyndicateAgentNukeops
 
 - type: entity
-  parent: ReinforcementRadioSyndicate
+  parent: ReinforcementRadio
   id: ReinforcementRadioSyndicateAncestor
   name: syndicate genetic ancestor reinforcement radio
   description: Calls in a specially trained ancestor of your choosing to assist you.
@@ -55,7 +70,7 @@
     selectablePrototypes: ["SyndicateMonkeyNukeops", "SyndicateKoboldNukeops"]
 
 - type: entity
-  parent: ReinforcementRadioSyndicate
+  parent: ReinforcementRadio
   id: ReinforcementRadioSyndicateSyndiCat
   name: syndicat reinforcement radio
   description: Calls in a faithfully trained cat with a microbomb to assist you.
@@ -72,7 +87,7 @@
     sound: /Audio/Animals/cat_meow.ogg
 
 - type: entity
-  parent: ReinforcementRadioSyndicate
+  parent: ReinforcementRadio
   id: ReinforcementRadioSyndicateCyborgAssault # Reinforcement radio exclusive to nukeops uplink
   name: syndicate assault cyborg reinforcement radio
   description: Call in a well armed assault cyborg, instantly!
index 59390d2b103c6206f536582d59982b79a62642c2..feb81097390525b2f96643466e8a8a95daa08865 100644 (file)
     - PinpointerSyndicateNuclear
     - DeathAcidifierImplanter
 
+- type: startingGear
+  id: SyndicateOperativeClothing
+  equipment:
+    jumpsuit: ClothingUniformJumpsuitOperative
+    back: ClothingBackpackSyndicate
+    shoes: ClothingShoesBootsCombatFilled
+    gloves: ClothingHandsGlovesColorBlack
+
+- type: startingGear
+  id: SyndicateReinforcementMedic
+  parent: SyndicateOperativeClothing
+  equipment:
+    pocket1: WeaponPistolViper
+  inhand:
+    - MedkitCombatFilled
+  storage:
+    back:
+    - BoxSurvivalSyndicate
+
+- type: startingGear
+  id: SyndicateReinforcementSpy
+  parent: SyndicateOperativeClothing
+  equipment:
+    id: AgentIDCard
+    mask: ClothingMaskGasVoiceChameleon
+    pocket1: WeaponPistolViper
+  storage:
+    back:
+    - BoxSurvivalSyndicate
+
+- type: startingGear
+  id: SyndicateReinforcementThief
+  parent: SyndicateOperativeClothing
+  equipment:
+    pocket1: WeaponPistolViper
+  inhand:
+    - ToolboxSyndicateFilled
+  storage:
+    back:
+    - BoxSurvivalSyndicate
+    - SyndicateJawsOfLife
+
 # Syndicate Reinforcement NukeOps
 - type: startingGear
   id: SyndicateOperativeGearReinforcementNukeOps
@@ -43,6 +85,7 @@
   equipment:
     id: SyndiPDA #Do not give a PDA to the normal Reinforcement - it will spawn with a 20TC uplink
 
+
 #Syndicate Operative Outfit - Basic
 - type: startingGear
   id: SyndicateOperativeGearBasic
index 24c0d8b3e3be0ecacd831e71b19f35c0324de24c..8e1827e81bf10cb7192db9a0519f33f6d3d2451b 100644 (file)
   name: ghost-role-information-syndicate-monkey-reinforcement-name
   description: ghost-role-information-syndicate-monkey-reinforcement-description
   rules: ghost-role-information-syndicate-monkey-reinforcement-name
-  entityPrototype: MobMonkeySyndicateAgentNukeops
\ No newline at end of file
+  entityPrototype: MobMonkeySyndicateAgentNukeops
+
+- type: ghostRole
+  id: SyndicateAgentMedic
+  name: ghost-role-information-syndicate-reinforcement-medic-name
+  description: ghost-role-information-syndicate-reinforcement-medic-description
+  rules: ghost-role-information-syndicate-monkey-reinforcement-rules
+  entityPrototype: MobHumanSyndicateAgentMedic
+  iconPrototype: MedkitCombat
+
+- type: ghostRole
+  id: SyndicateAgentSpy
+  name: ghost-role-information-syndicate-reinforcement-spy-name
+  description: ghost-role-information-syndicate-reinforcement-spy-description
+  rules: ghost-role-information-syndicate-monkey-reinforcement-rules
+  entityPrototype: MobHumanSyndicateAgentSpy
+  iconPrototype: ClothingMaskGasVoiceChameleon
+
+- type: ghostRole
+  id: SyndicateAgentThief
+  name: ghost-role-information-syndicate-reinforcement-thief-name
+  description: ghost-role-information-syndicate-reinforcement-thief-description
+  rules: ghost-role-information-syndicate-monkey-reinforcement-rules
+  entityPrototype: MobHumanSyndicateAgentThief
+  iconPrototype: SyndicateJawsOfLife