* 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>
152 lines
6.4 KiB
C#
152 lines
6.4 KiB
C#
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;
|
|
}
|
|
}
|