Chameleon controller implant (Clothing fast switch) (#33887)
* Add the chameleon controller implant * address the issues (Git please dont kill me) * Address the review and fix some merge conflicts! * Cleanup * Add use delay * Silly mistakes * Making a PR at 2 am: Gone wrong * Predict use delay and disable the buttons until you can choose another * First phase custom clothing * Better system, now relays to agent id and mindshield. Chameleon loadouts are a lot better to work with as well * Address the review! No more evil goto * Slams way is better I should have read more closely xD * Some of the jobs * Add to Cargo, CentComm, Service, Passenger, Ninja, Cluwne, Wizard + Minor changes to existing; Add chameleon to bandanas, medals, jugsuits and HUDs * Add everything else * Fix test * Job name * This looks better * Add department organization * Minor cleanup * Added some mindshields * Remove redudent comment and change funcion name to be clearer * Fix cluwne outfit * fix merge conflicts --------- Co-authored-by: SlamBamActionman <slambamactionman@gmail.com>
This commit is contained in:
5
Content.Client/Implants/ChameleonControllerSystem.cs
Normal file
5
Content.Client/Implants/ChameleonControllerSystem.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
using Content.Shared.Implants;
|
||||||
|
|
||||||
|
namespace Content.Client.Implants;
|
||||||
|
|
||||||
|
public sealed partial class ChameleonControllerSystem : SharedChameleonControllerSystem;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Shared.Clothing;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.Preferences.Loadouts;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Content.Shared.Timing;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Implants.UI;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class ChameleonControllerBoundUserInterface : BoundUserInterface
|
||||||
|
{
|
||||||
|
private readonly UseDelaySystem _delay;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private ChameleonControllerMenu? _menu;
|
||||||
|
|
||||||
|
public ChameleonControllerBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
|
{
|
||||||
|
_delay = EntMan.System<UseDelaySystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
|
||||||
|
_menu = this.CreateWindow<ChameleonControllerMenu>();
|
||||||
|
_menu.OnJobSelected += OnJobSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnJobSelected(ProtoId<ChameleonOutfitPrototype> outfit)
|
||||||
|
{
|
||||||
|
if (!EntMan.TryGetComponent<UseDelayComponent>(Owner, out var useDelayComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_delay.TryResetDelay((Owner, useDelayComp), true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SendMessage(new ChameleonControllerSelectedOutfitMessage(outfit));
|
||||||
|
|
||||||
|
if (!_delay.TryGetDelayInfo((Owner, useDelayComp), out var delay) || _menu == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_menu._lockedUntil = DateTime.Now.Add(delay.Length);
|
||||||
|
_menu.UpdateGrid(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Content.Client/Implants/UI/ChameleonControllerMenu.xaml
Normal file
12
Content.Client/Implants/UI/ChameleonControllerMenu.xaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
Title="{Loc 'chameleon-controller-ui-window-name'}"
|
||||||
|
MinSize="250 300"
|
||||||
|
SetSize="850 700">
|
||||||
|
<BoxContainer Orientation="Vertical" Margin="7 0 0 0">
|
||||||
|
<ScrollContainer VerticalExpand="True">
|
||||||
|
<GridContainer Name="Grid" Columns="3" Margin="0 5" >
|
||||||
|
</GridContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:FancyWindow>
|
||||||
157
Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs
Normal file
157
Content.Client/Implants/UI/ChameleonControllerMenu.xaml.cs
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Client.Roles;
|
||||||
|
using Content.Client.Stylesheets;
|
||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.StatusIcon;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Client.Implants.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class ChameleonControllerMenu : FancyWindow
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
private readonly SpriteSystem _sprite;
|
||||||
|
private readonly JobSystem _job;
|
||||||
|
|
||||||
|
// List of all the job protos that you can select!
|
||||||
|
private IEnumerable<ChameleonOutfitPrototype> _outfits;
|
||||||
|
|
||||||
|
// Lock the UI until this time
|
||||||
|
public DateTime? _lockedUntil;
|
||||||
|
|
||||||
|
private static readonly ProtoId<JobIconPrototype> UnknownIcon = "JobIconUnknown";
|
||||||
|
private static readonly LocId UnknownDepartment = "department-Unknown";
|
||||||
|
|
||||||
|
public event Action<ProtoId<ChameleonOutfitPrototype>>? OnJobSelected;
|
||||||
|
|
||||||
|
public ChameleonControllerMenu()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_sprite = _entityManager.System<SpriteSystem>();
|
||||||
|
_job = _entityManager.System<JobSystem>();
|
||||||
|
|
||||||
|
_outfits = _prototypeManager.EnumeratePrototypes<ChameleonOutfitPrototype>();
|
||||||
|
|
||||||
|
UpdateGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fill the grid with the correct job icons and buttons.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disabled">Set to true to disable all the buttons.</param>
|
||||||
|
public void UpdateGrid(bool disabled = false)
|
||||||
|
{
|
||||||
|
Grid.RemoveAllChildren();
|
||||||
|
|
||||||
|
// Dictionary to easily put outfits in departments.
|
||||||
|
// Department name -> UI element holding that department.
|
||||||
|
var departments = new Dictionary<string, BoxContainer>();
|
||||||
|
|
||||||
|
departments.Add(UnknownDepartment, CreateDepartment(UnknownDepartment));
|
||||||
|
|
||||||
|
// Go through every outfit and add them to the correct department.
|
||||||
|
foreach (var outfit in _outfits)
|
||||||
|
{
|
||||||
|
_prototypeManager.TryIndex(outfit.Job, out var jobProto);
|
||||||
|
|
||||||
|
var name = outfit.LoadoutName ?? outfit.Name ?? jobProto?.Name ?? "Prototype has no name or job.";
|
||||||
|
|
||||||
|
var jobIconId = outfit.Icon ?? jobProto?.Icon ?? UnknownIcon;
|
||||||
|
var jobIconProto = _prototypeManager.Index(jobIconId);
|
||||||
|
|
||||||
|
var outfitButton = CreateOutfitButton(disabled, name, jobIconProto, outfit.ID);
|
||||||
|
|
||||||
|
if (outfit.Job != null && _job.TryGetLowestWeightDepartment(outfit.Job, out var departmentPrototype))
|
||||||
|
{
|
||||||
|
if (!departments.ContainsKey(departmentPrototype.Name))
|
||||||
|
departments.Add(departmentPrototype.Name, CreateDepartment(departmentPrototype.Name));
|
||||||
|
|
||||||
|
departments[departmentPrototype.Name].AddChild(outfitButton);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
departments[UnknownDepartment].AddChild(outfitButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the departments by their weight.
|
||||||
|
var departmentList = departments.ToList();
|
||||||
|
departmentList.Sort((a, b) => a.Value.ChildCount.CompareTo(b.Value.ChildCount));
|
||||||
|
|
||||||
|
// Actually add the departments to the window.
|
||||||
|
foreach (var department in departmentList)
|
||||||
|
{
|
||||||
|
Grid.AddChild(department.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoxContainer CreateDepartment(string name)
|
||||||
|
{
|
||||||
|
var departmentContainer = new BoxContainer
|
||||||
|
{
|
||||||
|
Orientation = BoxContainer.LayoutOrientation.Vertical,
|
||||||
|
};
|
||||||
|
departmentContainer.AddChild(new Label
|
||||||
|
{
|
||||||
|
Text = Loc.GetString(name),
|
||||||
|
});
|
||||||
|
|
||||||
|
return departmentContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoxContainer CreateOutfitButton(bool disabled, string name, JobIconPrototype jobIconProto, ProtoId<ChameleonOutfitPrototype> outfitProto)
|
||||||
|
{
|
||||||
|
var outfitButton = new BoxContainer();
|
||||||
|
|
||||||
|
var button = new Button
|
||||||
|
{
|
||||||
|
HorizontalExpand = true,
|
||||||
|
StyleClasses = {StyleBase.ButtonSquare},
|
||||||
|
ToolTip = Loc.GetString(name),
|
||||||
|
Text = Loc.GetString(name),
|
||||||
|
Margin = new Thickness(0, 0, 15, 0),
|
||||||
|
Disabled = disabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
var jobIconTexture = new TextureRect
|
||||||
|
{
|
||||||
|
Texture = _sprite.Frame0(jobIconProto.Icon),
|
||||||
|
TextureScale = new Vector2(2.5f, 2.5f),
|
||||||
|
Stretch = TextureRect.StretchMode.KeepCentered,
|
||||||
|
Margin = new Thickness(0, 0, 5, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
outfitButton.AddChild(jobIconTexture);
|
||||||
|
outfitButton.AddChild(button);
|
||||||
|
|
||||||
|
button.OnPressed += _ => JobButtonPressed(outfitProto);
|
||||||
|
|
||||||
|
return outfitButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void JobButtonPressed(ProtoId<ChameleonOutfitPrototype> outfit)
|
||||||
|
{
|
||||||
|
OnJobSelected?.Invoke(outfit);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FrameUpdate(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.FrameUpdate(args);
|
||||||
|
|
||||||
|
if (_lockedUntil == null || DateTime.Now < _lockedUntil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lockedUntil = null;
|
||||||
|
UpdateGrid();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Content.Client.Implants;
|
||||||
|
using Content.IntegrationTests.Tests.Interaction;
|
||||||
|
using Content.Shared.Clothing;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.Preferences.Loadouts;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Chameleon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures all round <see cref="IsProbablyRoundStartJob">"round start jobs"</see> have an associated chameleon loadout.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ChameleonJobLoadoutTest : InteractionTest
|
||||||
|
{
|
||||||
|
private readonly List<ProtoId<JobPrototype>> JobBlacklist =
|
||||||
|
[
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task CheckAllJobs()
|
||||||
|
{
|
||||||
|
var alljobs = ProtoMan.EnumeratePrototypes<JobPrototype>();
|
||||||
|
|
||||||
|
// Job -> number of references
|
||||||
|
Dictionary<ProtoId<JobPrototype>, int> validJobs = new();
|
||||||
|
|
||||||
|
// Only add stuff that actually has clothing! We don't want stuff like AI or borgs.
|
||||||
|
foreach (var job in alljobs)
|
||||||
|
{
|
||||||
|
if (!IsProbablyRoundStartJob(job) || JobBlacklist.Contains(job.ID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
validJobs.Add(job.ID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var chameleons = ProtoMan.EnumeratePrototypes<ChameleonOutfitPrototype>();
|
||||||
|
|
||||||
|
foreach (var chameleon in chameleons)
|
||||||
|
{
|
||||||
|
if (chameleon.Job == null || !validJobs.ContainsKey(chameleon.Job.Value))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
validJobs[chameleon.Job.Value] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorMessage = new StringBuilder();
|
||||||
|
errorMessage.AppendLine("The following job(s) have no chameleon prototype(s):");
|
||||||
|
var invalid = false;
|
||||||
|
|
||||||
|
// All round start jobs have a chameleon loadout
|
||||||
|
foreach (var job in validJobs)
|
||||||
|
{
|
||||||
|
if (job.Value != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
errorMessage.AppendLine(job.Key + " has no chameleonOutfit prototype.");
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!invalid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Assert.Fail(errorMessage.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Best guess at what a "round start" job is.
|
||||||
|
/// </summary>
|
||||||
|
private bool IsProbablyRoundStartJob(JobPrototype job)
|
||||||
|
{
|
||||||
|
return job.StartingGear != null && ProtoMan.HasIndex<RoleLoadoutPrototype>(LoadoutSystem.GetJobPrototype(job.ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,11 @@ using Robust.Server.GameObjects;
|
|||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Server.Clothing.Systems;
|
||||||
|
using Content.Server.Implants;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.PDA;
|
||||||
|
|
||||||
namespace Content.Server.Access.Systems
|
namespace Content.Server.Access.Systems
|
||||||
{
|
{
|
||||||
@@ -18,6 +23,8 @@ namespace Content.Server.Access.Systems
|
|||||||
[Dependency] private readonly IdCardSystem _cardSystem = default!;
|
[Dependency] private readonly IdCardSystem _cardSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly ChameleonClothingSystem _chameleon = default!;
|
||||||
|
[Dependency] private readonly ChameleonControllerSystem _chamController = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -28,6 +35,46 @@ namespace Content.Server.Access.Systems
|
|||||||
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardNameChangedMessage>(OnNameChanged);
|
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardNameChangedMessage>(OnNameChanged);
|
||||||
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobChangedMessage>(OnJobChanged);
|
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobChangedMessage>(OnJobChanged);
|
||||||
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobIconChangedMessage>(OnJobIconChanged);
|
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobIconChangedMessage>(OnJobIconChanged);
|
||||||
|
SubscribeLocalEvent<AgentIDCardComponent, InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent>>(OnChameleonControllerOutfitChangedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChameleonControllerOutfitChangedItem(Entity<AgentIDCardComponent> ent, ref InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent> args)
|
||||||
|
{
|
||||||
|
if (!TryComp<IdCardComponent>(ent, out var idCardComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_prototypeManager.TryIndex(args.Args.ChameleonOutfit.Job, out var jobProto);
|
||||||
|
|
||||||
|
var jobIcon = args.Args.ChameleonOutfit.Icon ?? jobProto?.Icon;
|
||||||
|
var jobName = args.Args.ChameleonOutfit.Name ?? jobProto?.Name ?? "";
|
||||||
|
|
||||||
|
if (jobIcon != null)
|
||||||
|
_cardSystem.TryChangeJobIcon(ent, _prototypeManager.Index(jobIcon.Value), idCardComp);
|
||||||
|
|
||||||
|
if (jobName != "")
|
||||||
|
_cardSystem.TryChangeJobTitle(ent, Loc.GetString(jobName), idCardComp);
|
||||||
|
|
||||||
|
// If you have forced departments use those over the jobs actual departments.
|
||||||
|
if (args.Args.ChameleonOutfit?.Departments?.Count > 0)
|
||||||
|
_cardSystem.TryChangeJobDepartment(ent, args.Args.ChameleonOutfit.Departments, idCardComp);
|
||||||
|
else if (jobProto != null)
|
||||||
|
_cardSystem.TryChangeJobDepartment(ent, jobProto, idCardComp);
|
||||||
|
|
||||||
|
// Ensure that you chameleon IDs in PDAs correctly. Yes this is sus...
|
||||||
|
|
||||||
|
// There is one weird interaction: If the job / icon don't match the PDAs job the chameleon will be updated
|
||||||
|
// to the PDAs IDs sprite but the icon and job title will not match. There isn't a way to get around this
|
||||||
|
// really as there is no tie between job -> pda or pda -> job.
|
||||||
|
|
||||||
|
var idSlotGear = _chamController.GetGearForSlot(args, "id");
|
||||||
|
if (idSlotGear == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var proto = _prototypeManager.Index(idSlotGear);
|
||||||
|
if (!proto.TryGetComponent<PdaComponent>(out var comp, EntityManager.ComponentFactory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_chameleon.SetSelectedPrototype(ent, comp.IdCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args)
|
private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args)
|
||||||
|
|||||||
151
Content.Server/Implants/ChameleonControllerSystem.cs
Normal file
151
Content.Server/Implants/ChameleonControllerSystem.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
using Content.Server.Clothing.Systems;
|
||||||
|
using Content.Server.Preferences.Managers;
|
||||||
|
using Content.Shared.Clothing;
|
||||||
|
using Content.Shared.Clothing.Components;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.Implants.Components;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.Preferences;
|
||||||
|
using Content.Shared.Preferences.Loadouts;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Content.Shared.Station;
|
||||||
|
using Content.Shared.Timing;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Implants;
|
||||||
|
|
||||||
|
public sealed class ChameleonControllerSystem : SharedChameleonControllerSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
|
[Dependency] private readonly SharedStationSpawningSystem _stationSpawningSystem = default!;
|
||||||
|
[Dependency] private readonly ChameleonClothingSystem _chameleonClothingSystem = default!;
|
||||||
|
[Dependency] private readonly IServerPreferencesManager _preferences = default!;
|
||||||
|
[Dependency] private readonly UseDelaySystem _delay = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SubdermalImplantComponent, ChameleonControllerSelectedOutfitMessage>(OnSelected);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ChameleonClothingComponent, InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent>>(ChameleonControllerOutfitItemSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelected(Entity<SubdermalImplantComponent> ent, ref ChameleonControllerSelectedOutfitMessage args)
|
||||||
|
{
|
||||||
|
if (!_delay.TryResetDelay(ent.Owner, true) || ent.Comp.ImplantedEntity == null || !HasComp<ChameleonControllerImplantComponent>(ent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChangeChameleonClothingToOutfit(ent.Comp.ImplantedEntity.Value, args.SelectedChameleonOutfit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Switches all the chameleon clothing that the implant user is wearing to look like the selected job.
|
||||||
|
/// </summary>
|
||||||
|
private void ChangeChameleonClothingToOutfit(EntityUid user, ProtoId<ChameleonOutfitPrototype> outfit)
|
||||||
|
{
|
||||||
|
var outfitPrototype = _proto.Index(outfit);
|
||||||
|
|
||||||
|
_proto.TryIndex(outfitPrototype.Job, out var jobPrototype);
|
||||||
|
_proto.TryIndex(outfitPrototype.StartingGear, out var startingGearPrototype);
|
||||||
|
|
||||||
|
GetJobEquipmentInformation(jobPrototype, user, out var customRoleLoadout, out var defaultRoleLoadout, out var jobStartingGearPrototype);
|
||||||
|
|
||||||
|
var ev = new ChameleonControllerOutfitSelectedEvent(
|
||||||
|
outfitPrototype,
|
||||||
|
customRoleLoadout,
|
||||||
|
defaultRoleLoadout,
|
||||||
|
jobStartingGearPrototype,
|
||||||
|
startingGearPrototype
|
||||||
|
);
|
||||||
|
|
||||||
|
RaiseLocalEvent(user, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This gets as much information from the job as it can.
|
||||||
|
// E.g. the players profile, the default equipment for that job etc...
|
||||||
|
private void GetJobEquipmentInformation(
|
||||||
|
JobPrototype? jobPrototype,
|
||||||
|
EntityUid? user,
|
||||||
|
out RoleLoadout? customRoleLoadout,
|
||||||
|
out RoleLoadout? defaultRoleLoadout,
|
||||||
|
out StartingGearPrototype? jobStartingGearPrototype)
|
||||||
|
{
|
||||||
|
customRoleLoadout = null;
|
||||||
|
defaultRoleLoadout = null;
|
||||||
|
jobStartingGearPrototype = null;
|
||||||
|
|
||||||
|
if (jobPrototype == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_proto.TryIndex(jobPrototype.StartingGear, out jobStartingGearPrototype);
|
||||||
|
|
||||||
|
if (!TryComp<ActorComponent>(user, out var actorComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var userId = actorComponent.PlayerSession.UserId;
|
||||||
|
var prefs = _preferences.GetPreferences(userId);
|
||||||
|
|
||||||
|
if (prefs.SelectedCharacter is not HumanoidCharacterProfile profile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var jobProtoId = LoadoutSystem.GetJobPrototype(jobPrototype.ID);
|
||||||
|
|
||||||
|
profile.Loadouts.TryGetValue(jobProtoId, out customRoleLoadout);
|
||||||
|
|
||||||
|
if (!_proto.HasIndex<RoleLoadoutPrototype>(jobProtoId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
defaultRoleLoadout = new RoleLoadout(jobProtoId);
|
||||||
|
defaultRoleLoadout.SetDefault(profile, null, _proto); // only sets the default if the player has no loadout
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChameleonControllerOutfitItemSelected(Entity<ChameleonClothingComponent> ent, ref InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent> args)
|
||||||
|
{
|
||||||
|
if (!_inventory.TryGetContainingSlot(ent.Owner, out var slot))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_chameleonClothingSystem.SetSelectedPrototype(ent, GetGearForSlot(args, slot.Name), component: ent.Comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? GetGearForSlot(InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent> ev, string slotName)
|
||||||
|
{
|
||||||
|
return GetGearForSlot(ev.Args.ChameleonOutfit, ev.Args.CustomRoleLoadout, ev.Args.DefaultRoleLoadout, ev.Args.JobStartingGearPrototype, ev.Args.StartingGearPrototype, slotName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the gear for the given slot. The priority is:
|
||||||
|
/// <br/>1.) Custom loadout from the player for the slot.
|
||||||
|
/// <br/>2.) Chameleon outfit slot equipment.
|
||||||
|
/// <br/>3.) Chameleon outfit starting gear equipment.
|
||||||
|
/// <br/>4.) Default job equipment.
|
||||||
|
/// <br/>5.) Staring equipment for that job.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The entity (as a protoid) if there is gear for that slot, null if there isn't.</returns>
|
||||||
|
public string? GetGearForSlot(ChameleonOutfitPrototype? chameleonOutfitPrototype, RoleLoadout? customRoleLoadout, RoleLoadout? defaultRoleLoadout, StartingGearPrototype? jobStartingGearPrototype, StartingGearPrototype? startingGearPrototype, string slotName)
|
||||||
|
{
|
||||||
|
var customLoadoutGear = _stationSpawningSystem.GetGearForSlot(customRoleLoadout, slotName);
|
||||||
|
if (customLoadoutGear != null)
|
||||||
|
return customLoadoutGear;
|
||||||
|
|
||||||
|
if (chameleonOutfitPrototype != null && chameleonOutfitPrototype.Equipment.TryGetValue(slotName, out var forSlot))
|
||||||
|
return forSlot;
|
||||||
|
|
||||||
|
var startingGear = startingGearPrototype != null ? ((IEquipmentLoadout)startingGearPrototype).GetGear(slotName) : "";
|
||||||
|
if (startingGear != "")
|
||||||
|
return startingGear;
|
||||||
|
|
||||||
|
var defaultLoadoutGear = _stationSpawningSystem.GetGearForSlot(defaultRoleLoadout, slotName);
|
||||||
|
if (defaultLoadoutGear != null)
|
||||||
|
return defaultLoadoutGear;
|
||||||
|
|
||||||
|
var jobStartingGear = jobStartingGearPrototype != null ? ((IEquipmentLoadout)jobStartingGearPrototype).GetGear(slotName) : "";
|
||||||
|
if (jobStartingGear != "")
|
||||||
|
return jobStartingGear;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ using Content.Shared.Access.Components;
|
|||||||
using Content.Shared.CartridgeLoader;
|
using Content.Shared.CartridgeLoader;
|
||||||
using Content.Shared.Chat;
|
using Content.Shared.Chat;
|
||||||
using Content.Shared.DeviceNetwork.Components;
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
|
using Content.Shared.Implants;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Light;
|
using Content.Shared.Light;
|
||||||
using Content.Shared.Light.EntitySystems;
|
using Content.Shared.Light.EntitySystems;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
@@ -56,6 +58,14 @@ namespace Content.Server.PDA
|
|||||||
SubscribeLocalEvent<StationRenamedEvent>(OnStationRenamed);
|
SubscribeLocalEvent<StationRenamedEvent>(OnStationRenamed);
|
||||||
SubscribeLocalEvent<EntityRenamedEvent>(OnEntityRenamed, after: new[] { typeof(IdCardSystem) });
|
SubscribeLocalEvent<EntityRenamedEvent>(OnEntityRenamed, after: new[] { typeof(IdCardSystem) });
|
||||||
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
||||||
|
SubscribeLocalEvent<PdaComponent, InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent>>(ChameleonControllerOutfitItemSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChameleonControllerOutfitItemSelected(Entity<PdaComponent> ent, ref InventoryRelayedEvent<ChameleonControllerOutfitSelectedEvent> args)
|
||||||
|
{
|
||||||
|
// Relay it to your ID so it can update as well.
|
||||||
|
if (ent.Comp.ContainedId != null)
|
||||||
|
RaiseLocalEvent(ent.Comp.ContainedId.Value, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEntityRenamed(ref EntityRenamedEvent ev)
|
private void OnEntityRenamed(ref EntityRenamedEvent ev)
|
||||||
|
|||||||
@@ -204,6 +204,22 @@ public abstract class SharedIdCardSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryChangeJobDepartment(EntityUid uid, List<ProtoId<DepartmentPrototype>> departments, IdCardComponent? id = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
id.JobDepartments.Clear();
|
||||||
|
foreach (var department in departments)
|
||||||
|
{
|
||||||
|
id.JobDepartments.Add(department);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty(uid, id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to change the full name of a card.
|
/// Attempts to change the full name of a card.
|
||||||
/// Returns true/false.
|
/// Returns true/false.
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.Preferences.Loadouts;
|
||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Implants;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will allow anyone implanted with the implant to have more control over their chameleon clothing and items.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class ChameleonControllerImplantComponent : Component;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is sent when someone clicks on the hud icon and will open the menu.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class ChameleonControllerOpenMenuEvent : InstantActionEvent;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum ChameleonControllerKey : byte
|
||||||
|
{
|
||||||
|
Key,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class ChameleonControllerBuiState : BoundUserInterfaceState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the user clicks on a job in the menu.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class ChameleonControllerSelectedOutfitMessage(ProtoId<ChameleonOutfitPrototype> selectedOutfit) : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public readonly ProtoId<ChameleonOutfitPrototype> SelectedChameleonOutfit = selectedOutfit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is raised on clothing when the chameleon controller wants it to change sprite based off selecting an
|
||||||
|
/// outfit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ChameleonOutfit">The outfit being switched to.</param>
|
||||||
|
/// <param name="CustomRoleLoadout">The users custom loadout for the chameleon outfits job.</param>
|
||||||
|
/// <param name="DefaultRoleLoadout">The default loadout for the chameleon outfits job.</param>
|
||||||
|
/// <param name="JobStartingGearPrototype">The starting gear of the chameleon outfits job.</param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct ChameleonControllerOutfitSelectedEvent(
|
||||||
|
ChameleonOutfitPrototype ChameleonOutfit,
|
||||||
|
RoleLoadout? CustomRoleLoadout,
|
||||||
|
RoleLoadout? DefaultRoleLoadout,
|
||||||
|
StartingGearPrototype? JobStartingGearPrototype,
|
||||||
|
StartingGearPrototype? StartingGearPrototype
|
||||||
|
) : IInventoryRelayEvent
|
||||||
|
{
|
||||||
|
SlotFlags IInventoryRelayEvent.TargetSlots => SlotFlags.WITHOUT_POCKET;
|
||||||
|
}
|
||||||
64
Content.Shared/Implants/ChameleonOutfitPrototype.cs
Normal file
64
Content.Shared/Implants/ChameleonOutfitPrototype.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using Content.Shared.Roles;
|
||||||
|
using Content.Shared.StatusIcon;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Implants;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A chameleon clothing outfit. Used for the chameleon controller jobs! Has various fields to help describe a full
|
||||||
|
/// job - all the fields are optional and override each other if necessary so you should fill out the maximum amount
|
||||||
|
/// that make sense for the best outcome.
|
||||||
|
/// </summary>
|
||||||
|
[Prototype]
|
||||||
|
public sealed partial class ChameleonOutfitPrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[ViewVariables, IdDataField]
|
||||||
|
public string ID { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Job this outfit is based off of. Will use various things (job icon, job name, loadout etc...) for the outfit.
|
||||||
|
/// This has the lowest priority for clothing if the user has no custom loadout, but highest if they do.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<JobPrototype>? Job;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the outfit. This will be used for varous things like the chameleon controller UI and the agent IDs job
|
||||||
|
/// name.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId? Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This name is only used in the chameleon controller UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId? LoadoutName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generic staring gear. Sometimes outfits don't have jobs but do have starting gear (E.g. Cluwne).
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<StartingGearPrototype>? StartingGear;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Icon for the outfit - used for stuff like the UI or agent ID.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<JobIconPrototype>? Icon;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public List<ProtoId<DepartmentPrototype>>? Departments;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public bool HasMindShield;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom equipment for this specific chameleon outfit. If your making a new outfit that's just for the controller
|
||||||
|
/// use this! It can be mixed with the rest of the fields though, it just takes highest priority right under
|
||||||
|
/// user specified loadouts.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public Dictionary<string, EntProtoId> Equipment { get; set; } = new();
|
||||||
|
}
|
||||||
28
Content.Shared/Implants/SharedChameleonControllerSystem.cs
Normal file
28
Content.Shared/Implants/SharedChameleonControllerSystem.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Implants;
|
||||||
|
|
||||||
|
public abstract partial class SharedChameleonControllerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ChameleonControllerOpenMenuEvent>(OpenUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenUI(ChameleonControllerOpenMenuEvent ev)
|
||||||
|
{
|
||||||
|
var implant = ev.Action.Comp.Container;
|
||||||
|
|
||||||
|
if (!HasComp<ChameleonControllerImplantComponent>(implant))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_uiSystem.HasUi(implant.Value, ChameleonControllerKey.Key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_uiSystem.OpenUi(implant.Value, ChameleonControllerKey.Key, ev.Performer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ using Content.Shared.Explosion;
|
|||||||
using Content.Shared.Eye.Blinding.Systems;
|
using Content.Shared.Eye.Blinding.Systems;
|
||||||
using Content.Shared.Gravity;
|
using Content.Shared.Gravity;
|
||||||
using Content.Shared.IdentityManagement.Components;
|
using Content.Shared.IdentityManagement.Components;
|
||||||
|
using Content.Shared.Implants;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
@@ -51,6 +52,7 @@ public partial class InventorySystem
|
|||||||
SubscribeLocalEvent<InventoryComponent, ZombificationResistanceQueryEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, ZombificationResistanceQueryEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, IsEquippingTargetAttemptEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, IsEquippingTargetAttemptEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, IsUnequippingTargetAttemptEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, IsUnequippingTargetAttemptEvent>(RelayInventoryEvent);
|
||||||
|
SubscribeLocalEvent<InventoryComponent, ChameleonControllerOutfitSelectedEvent>(RelayInventoryEvent);
|
||||||
|
|
||||||
// by-ref events
|
// by-ref events
|
||||||
SubscribeLocalEvent<InventoryComponent, RefreshFrictionModifiersEvent>(RefRelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, RefreshFrictionModifiersEvent>(RefRelayInventoryEvent);
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Actions.Components;
|
||||||
|
using Content.Shared.Implants;
|
||||||
using Content.Shared.Mindshield.Components;
|
using Content.Shared.Mindshield.Components;
|
||||||
|
using Content.Shared.Tag;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Shared.Mindshield.FakeMindShield;
|
namespace Content.Shared.Mindshield.FakeMindShield;
|
||||||
|
|
||||||
public sealed class SharedFakeMindShieldSystem : EntitySystem
|
public sealed class SharedFakeMindShieldSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
|
[Dependency] private readonly TagSystem _tag = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
|
// This tag should be placed on the fake mindshield action so there is a way to easily identify it.
|
||||||
|
private static readonly ProtoId<TagPrototype> FakeMindShieldImplantTag = "FakeMindShieldImplant";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<FakeMindShieldComponent, FakeMindShieldToggleEvent>(OnToggleMindshield);
|
SubscribeLocalEvent<FakeMindShieldComponent, FakeMindShieldToggleEvent>(OnToggleMindshield);
|
||||||
|
SubscribeLocalEvent<FakeMindShieldComponent, ChameleonControllerOutfitSelectedEvent>(OnChameleonControllerOutfitSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnToggleMindshield(EntityUid uid, FakeMindShieldComponent comp, FakeMindShieldToggleEvent toggleEvent)
|
private void OnToggleMindshield(EntityUid uid, FakeMindShieldComponent comp, FakeMindShieldToggleEvent toggleEvent)
|
||||||
@@ -16,6 +29,48 @@ public sealed class SharedFakeMindShieldSystem : EntitySystem
|
|||||||
comp.IsEnabled = !comp.IsEnabled;
|
comp.IsEnabled = !comp.IsEnabled;
|
||||||
Dirty(uid, comp);
|
Dirty(uid, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnChameleonControllerOutfitSelected(EntityUid uid, FakeMindShieldComponent component, ChameleonControllerOutfitSelectedEvent args)
|
||||||
|
{
|
||||||
|
if (component.IsEnabled == args.ChameleonOutfit.HasMindShield)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// This assumes there is only one fake mindshield action per entity (This is currently enforced)
|
||||||
|
if (!TryComp<ActionsComponent>(uid, out var actionsComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// In case the fake mindshield ever doesn't have an action.
|
||||||
|
var actionFound = false;
|
||||||
|
|
||||||
|
foreach (var action in actionsComp.Actions)
|
||||||
|
{
|
||||||
|
if (!_tag.HasTag(action, FakeMindShieldImplantTag))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!TryComp<ActionComponent>(action, out var actionComp))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
actionFound = true;
|
||||||
|
|
||||||
|
if (_actions.IsCooldownActive(actionComp, _timing.CurTime))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
component.IsEnabled = args.ChameleonOutfit.HasMindShield;
|
||||||
|
Dirty(uid, component);
|
||||||
|
|
||||||
|
if (actionComp.UseDelay != null)
|
||||||
|
_actions.SetCooldown(action, actionComp.UseDelay.Value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they don't have the action for some reason, still set it correctly.
|
||||||
|
if (!actionFound)
|
||||||
|
{
|
||||||
|
component.IsEnabled = args.ChameleonOutfit.HasMindShield;
|
||||||
|
Dirty(uid, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed partial class FakeMindShieldToggleEvent : InstantActionEvent;
|
public sealed partial class FakeMindShieldToggleEvent : InstantActionEvent;
|
||||||
|
|||||||
@@ -100,6 +100,45 @@ public abstract class SharedJobSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get all the departments for a given job. Will return an empty list if none are found.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetAllDepartments(string jobProto, out List<DepartmentPrototype> departmentPrototypes)
|
||||||
|
{
|
||||||
|
// not sorting it since there should only be 1 primary department for a job.
|
||||||
|
// this is enforced by the job tests.
|
||||||
|
var departmentProtos = _prototypes.EnumeratePrototypes<DepartmentPrototype>();
|
||||||
|
departmentPrototypes = new List<DepartmentPrototype>();
|
||||||
|
var found = false;
|
||||||
|
|
||||||
|
foreach (var department in departmentProtos)
|
||||||
|
{
|
||||||
|
if (department.Roles.Contains(jobProto))
|
||||||
|
{
|
||||||
|
departmentPrototypes.Add(department);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get the lowest weighted department for the given job. If the job has no departments will return null.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetLowestWeightDepartment(string jobProto, [NotNullWhen(true)] out DepartmentPrototype? departmentPrototype)
|
||||||
|
{
|
||||||
|
departmentPrototype = null;
|
||||||
|
|
||||||
|
if (!TryGetAllDepartments(jobProto, out var departmentPrototypes) || departmentPrototypes.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
departmentPrototypes.Sort((x, y) => y.Weight.CompareTo(x.Weight));
|
||||||
|
|
||||||
|
departmentPrototype = departmentPrototypes[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
|
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -179,4 +179,34 @@ public abstract class SharedStationSpawningSystem : EntitySystem
|
|||||||
RaiseLocalEvent(entity, ref ev);
|
RaiseLocalEvent(entity, ref ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all the gear for a given slot when passed a loadout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="loadout">The loadout to look through.</param>
|
||||||
|
/// <param name="slot">The slot that you want the clothing for.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If there is a value for the given slot, it will return the proto id for that slot.
|
||||||
|
/// If nothing was found, will return null
|
||||||
|
/// </returns>
|
||||||
|
public string? GetGearForSlot(RoleLoadout? loadout, string slot)
|
||||||
|
{
|
||||||
|
if (loadout == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var group in loadout.SelectedLoadouts)
|
||||||
|
{
|
||||||
|
foreach (var items in group.Value)
|
||||||
|
{
|
||||||
|
if (!PrototypeManager.TryIndex(items.Prototype, out var loadoutPrototype))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var gear = ((IEquipmentLoadout) loadoutPrototype).GetGear(slot);
|
||||||
|
if (gear != string.Empty)
|
||||||
|
return gear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
chameleon-outfit-sus-name = Sus
|
||||||
1
Resources/Locale/en-US/implant/chameleon-controller.ftl
Normal file
1
Resources/Locale/en-US/implant/chameleon-controller.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
chameleon-controller-ui-window-name = Chameleon controls
|
||||||
@@ -8,3 +8,5 @@ department-Security = Security
|
|||||||
department-Science = Science
|
department-Science = Science
|
||||||
department-Silicon = Silicon
|
department-Silicon = Silicon
|
||||||
department-Specific = Station specific
|
department-Specific = Station specific
|
||||||
|
|
||||||
|
department-Unknown = Unknown
|
||||||
|
|||||||
@@ -382,6 +382,9 @@
|
|||||||
useDelay: 1
|
useDelay: 1
|
||||||
- type: InstantAction
|
- type: InstantAction
|
||||||
event: !type:FakeMindShieldToggleEvent
|
event: !type:FakeMindShieldToggleEvent
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- FakeMindShieldImplant
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseToggleAction
|
parent: BaseToggleAction
|
||||||
@@ -395,3 +398,15 @@
|
|||||||
state: icon-siren
|
state: icon-siren
|
||||||
useDelay: 1
|
useDelay: 1
|
||||||
itemIconStyle: BigAction
|
itemIconStyle: BigAction
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ActionChameleonController
|
||||||
|
name: Control clothing
|
||||||
|
description: Change your entire outfit fast!
|
||||||
|
components:
|
||||||
|
- type: Action
|
||||||
|
priority: -20
|
||||||
|
icon: { sprite: Actions/Implants/implants.rsi, state: chameleon }
|
||||||
|
itemIconStyle: BigAction
|
||||||
|
- type: InstantAction
|
||||||
|
event: !type:ChameleonControllerOpenMenuEvent
|
||||||
|
|||||||
@@ -211,7 +211,7 @@
|
|||||||
- id: ClothingEyesChameleon
|
- id: ClothingEyesChameleon
|
||||||
- id: ClothingHeadsetChameleon
|
- id: ClothingHeadsetChameleon
|
||||||
- id: ClothingShoesChameleon
|
- id: ClothingShoesChameleon
|
||||||
- id: BarberScissors
|
- id: ChameleonControllerImplanter
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingBackpackDuffelSyndicateBundle
|
parent: ClothingBackpackDuffelSyndicateBundle
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- HudMedical
|
- HudMedical
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: [ClothingEyesBase, ShowSecurityIcons, BaseSecurityContraband]
|
parent: [ClothingEyesBase, ShowSecurityIcons, BaseSecurityContraband]
|
||||||
@@ -58,6 +59,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- HudSecurity
|
- HudSecurity
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: [ClothingEyesBase, BaseCommandContraband]
|
parent: [ClothingEyesBase, BaseCommandContraband]
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
- Bandana
|
- Bandana
|
||||||
- ClothMade
|
- ClothMade
|
||||||
- Recyclable
|
- Recyclable
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: [ClothingHeadBandBase, ClothingMaskBandBlack]
|
parent: [ClothingHeadBandBase, ClothingMaskBandBlack]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -42,6 +44,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -56,6 +59,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -70,6 +74,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -84,6 +89,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -98,6 +104,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingNeckBase
|
parent: ClothingNeckBase
|
||||||
@@ -114,3 +121,4 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Medal
|
- Medal
|
||||||
|
- WhitelistChameleon
|
||||||
|
|||||||
@@ -665,6 +665,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- MonkeyWearable
|
- MonkeyWearable
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
#Wizard Hardsuit
|
#Wizard Hardsuit
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- HiViz
|
- HiViz
|
||||||
|
- WhitelistChameleon
|
||||||
|
|
||||||
#(Bartender) vest
|
#(Bartender) vest
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -246,6 +246,14 @@
|
|||||||
- type: Implanter
|
- type: Implanter
|
||||||
implant: DnaScramblerImplant
|
implant: DnaScramblerImplant
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ChameleonControllerImplanter
|
||||||
|
suffix: chameleon controller
|
||||||
|
parent: BaseImplantOnlyImplanterSyndi
|
||||||
|
components:
|
||||||
|
- type: Implanter
|
||||||
|
implant: ChameleonControllerImplant
|
||||||
|
|
||||||
#Nuclear Operative/Special implanters
|
#Nuclear Operative/Special implanters
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -212,6 +212,23 @@
|
|||||||
components:
|
components:
|
||||||
- HumanoidAppearance # syndies cant turn hamlet into a human
|
- HumanoidAppearance # syndies cant turn hamlet into a human
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
categories: [ HideSpawnMenu, Spawner ]
|
||||||
|
parent: BaseSubdermalImplant
|
||||||
|
id: ChameleonControllerImplant
|
||||||
|
name: chameleon controller implant
|
||||||
|
description: This implant allows you to instantly change the appearance of all worn chameleon clothing.
|
||||||
|
components:
|
||||||
|
- type: ChameleonControllerImplant
|
||||||
|
- type: SubdermalImplant
|
||||||
|
implantAction: ActionChameleonController
|
||||||
|
- type: UseDelay
|
||||||
|
delay: 1
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
enum.ChameleonControllerKey.Key:
|
||||||
|
type: ChameleonControllerBoundUserInterface
|
||||||
|
|
||||||
#Nuclear Operative/Special Exclusive implants
|
#Nuclear Operative/Special Exclusive implants
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -33,3 +33,11 @@
|
|||||||
- Wirecutter
|
- Wirecutter
|
||||||
- Welder
|
- Welder
|
||||||
- Multitool
|
- Multitool
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: NinjaChameleonOutfit
|
||||||
|
name: roles-antag-space-ninja-name
|
||||||
|
startingGear: SpaceNinjaGear
|
||||||
|
equipment:
|
||||||
|
id: PassengerPDA
|
||||||
|
neck: ClothingNeckGoldmedal
|
||||||
|
|||||||
@@ -65,6 +65,15 @@
|
|||||||
equipment:
|
equipment:
|
||||||
pocket2: BaseUplinkRadio40TC
|
pocket2: BaseUplinkRadio40TC
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: NukeopsOutfit
|
||||||
|
name: roles-antag-nuclear-operative-name
|
||||||
|
startingGear: SyndicateOperativeGearFullNoUplink
|
||||||
|
icon: "JobIconSyndicate"
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitSyndie
|
||||||
|
neck: ClothingNeckScarfStripedSyndieRed
|
||||||
|
|
||||||
#Nuclear Operative Commander Gear
|
#Nuclear Operative Commander Gear
|
||||||
- type: startingGear
|
- type: startingGear
|
||||||
id: SyndicateCommanderGearFull
|
id: SyndicateCommanderGearFull
|
||||||
@@ -75,6 +84,15 @@
|
|||||||
inhand:
|
inhand:
|
||||||
- NukeOpsDeclarationOfWar
|
- NukeOpsDeclarationOfWar
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: NukeopsCommanderOutfit
|
||||||
|
name: roles-antag-nuclear-operative-commander-name
|
||||||
|
startingGear: SyndicateCommanderGearFull
|
||||||
|
icon: "JobIconSyndicate"
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitSyndieCommander
|
||||||
|
neck: ClothingNeckScarfStripedSyndieGreen
|
||||||
|
|
||||||
#Nuclear Operative Medic Gear
|
#Nuclear Operative Medic Gear
|
||||||
- type: startingGear
|
- type: startingGear
|
||||||
id: SyndicateOperativeMedicFull
|
id: SyndicateOperativeMedicFull
|
||||||
@@ -97,6 +115,15 @@
|
|||||||
- CombatMedipen
|
- CombatMedipen
|
||||||
- DeathAcidifierImplanter
|
- DeathAcidifierImplanter
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: NukeopsMedicOutfit
|
||||||
|
name: roles-antag-nuclear-operative-agent-name
|
||||||
|
startingGear: SyndicateOperativeMedicFull
|
||||||
|
icon: "JobIconSyndicate"
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitSyndieMedic
|
||||||
|
neck: ClothingNeckScarfStripedLightBlue
|
||||||
|
|
||||||
#Lone Operative Gear
|
#Lone Operative Gear
|
||||||
- type: startingGear
|
- type: startingGear
|
||||||
id: SyndicateLoneOperativeGearFull
|
id: SyndicateLoneOperativeGearFull
|
||||||
|
|||||||
@@ -25,3 +25,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: CargoTechnicianChameleonOutfit
|
||||||
|
job: CargoTechnician
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatCargosoft
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
outerClothing: ClothingOuterWinterCargo
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
gloves: ClothingHandsGlovesFingerless
|
||||||
|
|||||||
@@ -44,3 +44,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: QuartermasterChameleonOutfit
|
||||||
|
job: Quartermaster
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatQMsoft
|
||||||
|
eyes: ClothingEyesGlassesSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
outerClothing: ClothingOuterWinterQM
|
||||||
|
neck: ClothingNeckCloakQm
|
||||||
|
gloves: ClothingHandsKnuckleDustersQM
|
||||||
|
|||||||
@@ -25,3 +25,15 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: SalvageSpecialistChameleonOutfit
|
||||||
|
job: SalvageSpecialist
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatCargosoft
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskGasExplorer
|
||||||
|
outerClothing: ClothingOuterWinterMiner
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|
||||||
|
|||||||
@@ -38,3 +38,11 @@
|
|||||||
- GrenadeFlashBang
|
- GrenadeFlashBang
|
||||||
- PillAmbuzolPlus
|
- PillAmbuzolPlus
|
||||||
- PillAmbuzol
|
- PillAmbuzol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: CBURNChameleonOutfit
|
||||||
|
job: CBURN
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetCBURN
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
|||||||
@@ -45,3 +45,11 @@
|
|||||||
- FreedomImplanter
|
- FreedomImplanter
|
||||||
inhand:
|
inhand:
|
||||||
- WeaponPulseRifle
|
- WeaponPulseRifle
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: DeathSquadChameleonOutfit
|
||||||
|
job: DeathSquad
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitDeathsquad
|
||||||
|
neck: ClothingNeckBronzeheart
|
||||||
|
|||||||
@@ -91,6 +91,14 @@
|
|||||||
- CrowbarRed
|
- CrowbarRed
|
||||||
- MagazineMagnum
|
- MagazineMagnum
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTLeaderChameleonOutfit
|
||||||
|
job: ERTLeader
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTLeader
|
||||||
|
neck: ClothingNeckBronzeheart
|
||||||
|
|
||||||
# Chaplain
|
# Chaplain
|
||||||
- type: job
|
- type: job
|
||||||
id: ERTChaplain
|
id: ERTChaplain
|
||||||
@@ -175,6 +183,16 @@
|
|||||||
- FoodBakedBunHotX
|
- FoodBakedBunHotX
|
||||||
- Lighter
|
- Lighter
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTChaplainChameleonOutfit
|
||||||
|
job: ERTChaplain
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTChaplain
|
||||||
|
mask: ClothingMaskGasERT
|
||||||
|
outerClothing: ClothingOuterHardsuitERTChaplain
|
||||||
|
shoes: ClothingShoesBootsMagAdv
|
||||||
|
|
||||||
# Engineer
|
# Engineer
|
||||||
- type: job
|
- type: job
|
||||||
id: ERTEngineer
|
id: ERTEngineer
|
||||||
@@ -250,6 +268,14 @@
|
|||||||
- SheetSteel
|
- SheetSteel
|
||||||
- SheetGlass
|
- SheetGlass
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTEngineerChameleonOutfit
|
||||||
|
job: ERTEngineer
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTEngineer
|
||||||
|
neck: ClothingNeckEngineermedal
|
||||||
|
|
||||||
# Security
|
# Security
|
||||||
- type: job
|
- type: job
|
||||||
id: ERTSecurity
|
id: ERTSecurity
|
||||||
@@ -257,7 +283,7 @@
|
|||||||
description: job-description-ertsecurity
|
description: job-description-ertsecurity
|
||||||
playTimeTracker: JobERTSecurity
|
playTimeTracker: JobERTSecurity
|
||||||
setPreference: false
|
setPreference: false
|
||||||
startingGear: ERTEngineerGearEVA
|
startingGear: ERTSecurityGearEVA
|
||||||
icon: "JobIconNanotrasen"
|
icon: "JobIconNanotrasen"
|
||||||
supervisors: job-supervisors-centcom
|
supervisors: job-supervisors-centcom
|
||||||
canBeAntag: false
|
canBeAntag: false
|
||||||
@@ -343,6 +369,14 @@
|
|||||||
- CrowbarRed
|
- CrowbarRed
|
||||||
- MagazinePistol
|
- MagazinePistol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTSecurityChameleonOutfit
|
||||||
|
job: ERTSecurity
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTSecurity
|
||||||
|
neck: ClothingNeckSecuritymedal
|
||||||
|
|
||||||
# Medical
|
# Medical
|
||||||
- type: job
|
- type: job
|
||||||
id: ERTMedical
|
id: ERTMedical
|
||||||
@@ -410,6 +444,14 @@
|
|||||||
- ChemistryBottleEpinephrine
|
- ChemistryBottleEpinephrine
|
||||||
- ChemistryBottleEpinephrine
|
- ChemistryBottleEpinephrine
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTMedicalChameleonOutfit
|
||||||
|
job: ERTMedical
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTMedical
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
|
||||||
# Janitor
|
# Janitor
|
||||||
- type: job
|
- type: job
|
||||||
id: ERTJanitor
|
id: ERTJanitor
|
||||||
@@ -472,3 +514,12 @@
|
|||||||
- Soap
|
- Soap
|
||||||
- CrowbarRed
|
- CrowbarRed
|
||||||
- AdvMopItem
|
- AdvMopItem
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ERTJanitorChameleonOutfit
|
||||||
|
job: ERTJanitor
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetHardsuitERTJanitor
|
||||||
|
neck: ClothingNeckScarfStripedPurple
|
||||||
|
eyes: ClothingEyesGlassesSunglasses
|
||||||
|
|||||||
@@ -30,3 +30,12 @@
|
|||||||
belt: WeaponPistolN1984
|
belt: WeaponPistolN1984
|
||||||
pocket1: BoxFolderBlack
|
pocket1: BoxFolderBlack
|
||||||
pocket2: PenCentcom
|
pocket2: PenCentcom
|
||||||
|
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: CentralCommandOfficialOutfit
|
||||||
|
job: CentralCommandOfficial
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
neck: ClothingNeckScarfStripedCentcom
|
||||||
|
mask: ClothingMaskGasCentcom
|
||||||
|
|||||||
@@ -17,3 +17,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: PassengerChameleonOutfit
|
||||||
|
job: Passenger
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatWelding
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckMantle
|
||||||
|
outerClothing: ClothingOuterWinterCoat
|
||||||
|
gloves: ClothingHandsGlovesColorYellowBudget
|
||||||
|
|||||||
@@ -27,3 +27,15 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: BartenderChameleonOutfit
|
||||||
|
job: Bartender
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatTophat
|
||||||
|
eyes: ClothingEyesGlassesSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckScarfStripedBlack
|
||||||
|
outerClothing: ClothingOuterArmorBasicSlim
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|
||||||
|
|||||||
@@ -28,3 +28,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: BotanistChameleonOutfit
|
||||||
|
job: Botanist
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadBandBotany
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckScarfStripedGreen
|
||||||
|
outerClothing: ClothingOuterApronBotanist
|
||||||
|
gloves: ClothingHandsGlovesLeather
|
||||||
|
|||||||
@@ -24,3 +24,15 @@
|
|||||||
back:
|
back:
|
||||||
- Bible
|
- Bible
|
||||||
- RubberStampChaplain
|
- RubberStampChaplain
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ChaplainChameleonOutfit
|
||||||
|
job: Chaplain
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatPlaguedoctor
|
||||||
|
eyes: ClothingEyesGlasses
|
||||||
|
mask: ClothingMaskPlague
|
||||||
|
neck: ClothingNeckStoleChaplain
|
||||||
|
outerClothing: ClothingOuterPlagueSuit
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|
||||||
|
|||||||
@@ -28,3 +28,15 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ChefChameleonOutfit
|
||||||
|
job: Chef
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatChef
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskItalianMoustache
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
outerClothing: ClothingOuterJacketChef
|
||||||
|
gloves: ClothingHandsGlovesColorWhite
|
||||||
|
shoes: ClothingShoesChef
|
||||||
|
|||||||
@@ -37,3 +37,13 @@
|
|||||||
back:
|
back:
|
||||||
- RubberStampClown
|
- RubberStampClown
|
||||||
- CrayonRainbow
|
- CrayonRainbow
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ClownChameleonOutfit
|
||||||
|
job: Clown
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatXmasCrown
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
neck: ClothingHeadHatFlowerWreath
|
||||||
|
outerClothing: ClothingOuterClownPriest
|
||||||
|
gloves: ClothingHandsGlovesColorYellowBudget
|
||||||
|
|||||||
@@ -35,3 +35,14 @@
|
|||||||
head: ClothingHeadHatCatEars
|
head: ClothingHeadHatCatEars
|
||||||
ears: ClothingHeadsetService
|
ears: ClothingHeadsetService
|
||||||
belt: ClothingBeltJanitorFilled
|
belt: ClothingBeltJanitorFilled
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: JanitorChameleonOutfit
|
||||||
|
job: Janitor
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatPurplesoft
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckScarfStripedPurple
|
||||||
|
outerClothing: ClothingOuterWinterJani
|
||||||
|
gloves: ClothingHandsGlovesJanitor
|
||||||
|
|||||||
@@ -27,3 +27,14 @@
|
|||||||
back:
|
back:
|
||||||
- RubberStampLawyer
|
- RubberStampLawyer
|
||||||
- BookSpaceLaw
|
- BookSpaceLaw
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: LawyerChameleonOutfit
|
||||||
|
job: Lawyer
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBowlerHat
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckLawyerbadge
|
||||||
|
outerClothing: ClothingOuterWinterColorBlack
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -21,3 +21,14 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- BookRandom
|
- BookRandom
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: LibrarianChameleonOutfit
|
||||||
|
job: Librarian
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatCanadaBeanie
|
||||||
|
eyes: ClothingEyesGlassesJamjar
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckScarfStripedGreen
|
||||||
|
outerClothing: ClothingOuterWinterColorGreen
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -45,3 +45,12 @@
|
|||||||
state: full
|
state: full
|
||||||
- type: InstantAction
|
- type: InstantAction
|
||||||
event: !type:InvisibleWallActionEvent
|
event: !type:InvisibleWallActionEvent
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: MimeChameleonOutfit
|
||||||
|
job: Mime
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatMimesoft
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
neck: ClothingNeckScarfStripedZebra
|
||||||
|
outerClothing: ClothingOuterWinterMime
|
||||||
|
|||||||
@@ -24,3 +24,13 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: MusicianChameleonOutfit
|
||||||
|
job: Musician
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatTophat
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckHeadphones
|
||||||
|
outerClothing: ClothingOuterWinterMusician
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -27,3 +27,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ServiceWorkerChameleonOutfit
|
||||||
|
job: ServiceWorker
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBowlerHat
|
||||||
|
eyes: ClothingEyesGlassesSunglasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
outerClothing: ClothingOuterVest
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -46,3 +46,13 @@
|
|||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
# - StationCharter
|
# - StationCharter
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: CaptainChameleonOutfit
|
||||||
|
job: Captain
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatCapcap
|
||||||
|
eyes: ClothingEyesGlassesCommand
|
||||||
|
mask: ClothingMaskGasCaptain
|
||||||
|
neck: ClothingNeckCloakCap
|
||||||
|
|||||||
@@ -69,3 +69,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: HeadOfPersonnelChameleonOutfit
|
||||||
|
job: HeadOfPersonnel
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatHopcap
|
||||||
|
eyes: ClothingEyesHudCommand
|
||||||
|
mask: ClothingMaskNeckGaiterRed
|
||||||
|
neck: ClothingNeckCloakHop
|
||||||
|
outerClothing: ClothingOuterWinterHoP
|
||||||
|
|
||||||
|
|||||||
@@ -30,3 +30,13 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: AtmosphericTechnicianChameleonOutfit
|
||||||
|
job: AtmosphericTechnician
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetAtmosFire
|
||||||
|
mask: ClothingMaskGasAtmos
|
||||||
|
neck: ClothingNeckScarfStripedLightBlue
|
||||||
|
outerClothing: ClothingOuterSuitAtmosFire
|
||||||
|
gloves: ClothingHandsGlovesColorYellow
|
||||||
|
|||||||
@@ -44,3 +44,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ChiefEngineerChameleonOutfit
|
||||||
|
job: ChiefEngineer
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretEngineering
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckCloakCe
|
||||||
|
outerClothing: ClothingOuterWinterCE
|
||||||
|
gloves: ClothingHandsGlovesColorYellow
|
||||||
|
shoes: ClothingShoesBootsMagAdv
|
||||||
|
|||||||
@@ -26,3 +26,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: StationEngineerChameleonOutfit
|
||||||
|
job: StationEngineer
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatHardhatYellow
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckScarfStripedOrange
|
||||||
|
outerClothing: ClothingOuterWinterEngi
|
||||||
|
gloves: ClothingHandsGlovesColorYellow
|
||||||
|
shoes: ClothingShoesBootsMag
|
||||||
|
|||||||
@@ -30,3 +30,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: TechnicalAssistantChameleonOutfit
|
||||||
|
job: TechnicalAssistant
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatHardhatOrange
|
||||||
|
eyes: ClothingEyesGlassesMeson
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckScarfStripedOrange
|
||||||
|
outerClothing: ClothingOuterVestHazard
|
||||||
|
gloves: ClothingHandsGlovesColorYellow
|
||||||
|
|||||||
@@ -14,3 +14,14 @@
|
|||||||
equipment:
|
equipment:
|
||||||
pocket1: BikeHorn
|
pocket1: BikeHorn
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: CluwneChameleonOutfit
|
||||||
|
name: job-title-cluwne
|
||||||
|
startingGear: CluwneGear
|
||||||
|
icon: JobIconCluwne
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatXmasCrown
|
||||||
|
eyes: ClothingEyesBlindfold
|
||||||
|
ears: ClothingHeadsetGrey
|
||||||
|
neck: ClothingHeadHatFlowerWreath
|
||||||
|
outerClothing: ClothingOuterClownPriest
|
||||||
|
|||||||
17
Resources/Prototypes/Roles/Jobs/Fun/sus.yml
Normal file
17
Resources/Prototypes/Roles/Jobs/Fun/sus.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
- type: chameleonOutfit
|
||||||
|
id: SusChameleonOutfit
|
||||||
|
loadoutName: chameleon-outfit-sus-name
|
||||||
|
name: job-name-passenger
|
||||||
|
icon: "JobIconPassenger"
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeret
|
||||||
|
eyes: ClothingEyesGlassesSunglasses
|
||||||
|
ears: ClothingHeadsetGrey
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
outerClothing: ClothingOuterVest
|
||||||
|
jumpsuit: ClothingUniformJumpsuitColorBlack
|
||||||
|
neck: ClothingNeckScarfStripedRed
|
||||||
|
back: ClothingBackpack
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
shoes: ClothingShoesColorBlack
|
||||||
|
id: PassengerPDA
|
||||||
@@ -28,3 +28,13 @@
|
|||||||
jumpsuit: ClothingUniformJumpsuitColorPurple
|
jumpsuit: ClothingUniformJumpsuitColorPurple
|
||||||
head: ClothingHeadHatVioletwizard
|
head: ClothingHeadHatVioletwizard
|
||||||
outerClothing: ClothingOuterWizardViolet
|
outerClothing: ClothingOuterWizardViolet
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: WizardChameleonOutfit
|
||||||
|
name: roles-antag-wizard-name
|
||||||
|
startingGear: WizardBlueGear
|
||||||
|
equipment:
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
neck: ClothingNeckLGBTPin
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -26,3 +26,13 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ChemistChameleonOutfit
|
||||||
|
job: Chemist
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretMedic
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
outerClothing: ClothingOuterCoatLabChem
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -44,3 +44,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ChiefMedicalOfficerChameleonOutfit
|
||||||
|
job: ChiefMedicalOfficer
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretCmo
|
||||||
|
eyes: ClothingEyesHudMedical
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
neck: ClothingCloakCmo
|
||||||
|
outerClothing: ClothingOuterCoatLabCmo
|
||||||
|
gloves: ClothingHandsGlovesNitrile
|
||||||
|
|||||||
@@ -28,3 +28,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: MedicalDoctorChameleonOutfit
|
||||||
|
job: MedicalDoctor
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadNurseHat
|
||||||
|
eyes: ClothingEyesHudMedical
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
outerClothing: ClothingOuterCoatLab
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -27,3 +27,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: MedicalInternChameleonOutfit
|
||||||
|
job: MedicalIntern
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretMedic
|
||||||
|
eyes: ClothingEyesHudMedical
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
outerClothing: ClothingOuterCoatLabOpened
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -25,3 +25,14 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- EmergencyRollerBedSpawnFolded
|
- EmergencyRollerBedSpawnFolded
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ParamedicChameleonOutfit
|
||||||
|
job: Paramedic
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatParamedicsoft
|
||||||
|
eyes: ClothingEyesHudMedical
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
outerClothing: ClothingOuterCoatParamedicWB
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -26,3 +26,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ResearchAssistantChameleonOutfit
|
||||||
|
job: ResearchAssistant
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatCardborg
|
||||||
|
eyes: ClothingEyesGlasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckScarfStripedPurple
|
||||||
|
outerClothing: ClothingOuterCoatLab
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -37,3 +37,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ResearchDirectorChameleonOutfit
|
||||||
|
job: ResearchDirector
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretRND
|
||||||
|
eyes: ClothingEyesGlasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckCloakRd
|
||||||
|
outerClothing: ClothingOuterCoatRD
|
||||||
|
gloves: ClothingHandsGlovesColorPurple
|
||||||
|
|||||||
@@ -21,3 +21,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ScientistChameleonOutfit
|
||||||
|
job: Scientist
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadBandSkull
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskGas
|
||||||
|
neck: ClothingNeckTieSci
|
||||||
|
outerClothing: ClothingOuterCoatRnd
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -35,3 +35,13 @@
|
|||||||
- Flash
|
- Flash
|
||||||
- ForensicPad
|
- ForensicPad
|
||||||
- ForensicScanner
|
- ForensicScanner
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: DetectiveChameleonOutfit
|
||||||
|
job: Detective
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatFedoraBrown
|
||||||
|
mask: ClothingMaskGasSecurity
|
||||||
|
neck: ClothingNeckTieDet
|
||||||
|
gloves: ClothingHandsGlovesForensic
|
||||||
|
|||||||
@@ -51,3 +51,11 @@
|
|||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
- MagazinePistol
|
- MagazinePistol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: HeadOfSecurityChameleonOutfit
|
||||||
|
job: HeadOfSecurity
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
mask: ClothingMaskGasSecurity
|
||||||
|
neck: ClothingNeckCloakHos
|
||||||
|
|||||||
@@ -39,3 +39,15 @@
|
|||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
- MagazinePistol
|
- MagazinePistol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: SecurityCadetChameleonOutfit
|
||||||
|
job: SecurityCadet
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHelmetBasic
|
||||||
|
eyes: ClothingEyesHudSecurity
|
||||||
|
mask: ClothingMaskGasSecurity
|
||||||
|
neck: ClothingNeckScarfStripedRed
|
||||||
|
belt: ClothingBeltSecurity
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -32,3 +32,13 @@
|
|||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
- MagazinePistol
|
- MagazinePistol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: SecurityOfficerChameleonOutfit
|
||||||
|
job: SecurityOfficer
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretSecurity
|
||||||
|
mask: ClothingMaskGasSecurity
|
||||||
|
neck: Dinkystar
|
||||||
|
gloves: ClothingHandsGlovesColorBlack
|
||||||
|
|||||||
@@ -39,3 +39,17 @@
|
|||||||
back:
|
back:
|
||||||
- Flash
|
- Flash
|
||||||
- MagazinePistol
|
- MagazinePistol
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: WardenChameleonOutfit
|
||||||
|
job: Warden
|
||||||
|
hasMindShield: true
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatWarden
|
||||||
|
mask: ClothingMaskGasSecurity
|
||||||
|
outerClothing: ClothingOuterCoatWarden
|
||||||
|
jumpsuit: ClothingUniformJumpsuitWarden
|
||||||
|
neck: Dinkystar
|
||||||
|
belt: ClothingBeltSecurity
|
||||||
|
gloves: ClothingHandsGlovesCombat
|
||||||
|
shoes: ClothingShoesBootsJack
|
||||||
|
|||||||
@@ -24,3 +24,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: BoxerChameleonOutfit
|
||||||
|
job: Boxer
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBlacksoft
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
outerClothing: ClothingOuterWinterColorGray
|
||||||
|
jumpsuit: UniformShortsRedWithTop
|
||||||
|
neck: ClothingNeckScarfStripedRed
|
||||||
|
|||||||
@@ -21,3 +21,15 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- RubberStampPsychologist
|
- RubberStampPsychologist
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: PsychologistChameleonOutfit
|
||||||
|
job: Psychologist
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatBeretMedic
|
||||||
|
eyes: ClothingEyesHudMedical
|
||||||
|
mask: ClothingMaskSterile
|
||||||
|
outerClothing: ClothingOuterCoatLab
|
||||||
|
neck: ClothingNeckStethoscope
|
||||||
|
belt: ClothingBeltMedical
|
||||||
|
gloves: ClothingHandsGlovesLatex
|
||||||
|
|||||||
@@ -19,3 +19,14 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ReporterChameleonOutfit
|
||||||
|
job: Reporter
|
||||||
|
equipment:
|
||||||
|
head: ClothingHeadHatFedoraGrey
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
outerClothing: ClothingOuterCoatTrench
|
||||||
|
neck: ClothingNeckTieRed
|
||||||
|
gloves: ClothingHandsGlovesFingerless
|
||||||
|
|||||||
@@ -25,3 +25,15 @@
|
|||||||
#storage:
|
#storage:
|
||||||
#back:
|
#back:
|
||||||
#- Stuff
|
#- Stuff
|
||||||
|
|
||||||
|
- type: chameleonOutfit
|
||||||
|
id: ZookeeperChameleonOutfit
|
||||||
|
job: Zookeeper
|
||||||
|
equipment:
|
||||||
|
eyes: ClothingEyesGlassesCheapSunglasses
|
||||||
|
mask: ClothingMaskBreath
|
||||||
|
outerClothing: ClothingOuterWinterColorLightBrown
|
||||||
|
neck: ClothingNeckScarfStripedBrown
|
||||||
|
belt: ClothingBeltStorageWaistbag
|
||||||
|
gloves: ClothingHandsGlovesColorBrown
|
||||||
|
|
||||||
|
|||||||
@@ -932,6 +932,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: MimeHappyHonk
|
id: MimeHappyHonk
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: FakeMindShieldImplant
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: MindTransferTarget
|
id: MindTransferTarget
|
||||||
|
|
||||||
|
|||||||
BIN
Resources/Textures/Actions/Implants/implants.rsi/chameleon.png
Normal file
BIN
Resources/Textures/Actions/Implants/implants.rsi/chameleon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 871 B |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC-BY-SA-3.0",
|
"license": "CC-BY-SA-3.0",
|
||||||
"copyright": "Implant icons taken from Citadel Station at commit https://github.com/Citadel-Station-13/Citadel-Station-13/commit/a2f6a7c20763da3d2f3cfb982e9ccd7922df6162",
|
"copyright": "Implant icons taken from Citadel Station at commit https://github.com/Citadel-Station-13/Citadel-Station-13/commit/a2f6a7c20763da3d2f3cfb982e9ccd7922df6162. The chameleon icon is a combination of the red beret (https://github.com/tgstation/tgstation/commit/4f6190e2895e09116663ef282d3ce1d8b35c032e) and the CMO beret (https://github.com/space-wizards/space-station-14/pull/13489) made by Beck",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "explosive"
|
"name": "explosive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chameleon"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user