From 8f12e90b90a6749d783b1f2c8588241749ceeeb2 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:53:42 +1000 Subject: [PATCH] Don't use invalid defaults for loadouts (#28740) * Don't use invalid defaults for loadouts At the time it made more sense but now with species specific stuff it's better to have nothing. * Loadout SetDefault only applies valid loadouts --- Content.Client/Lobby/LobbyUIController.cs | 4 +-- .../Lobby/UI/HumanoidProfileEditor.xaml.cs | 2 +- .../Station/Systems/StationSpawningSystem.cs | 19 ++++++------- Content.Shared/Clothing/LoadoutSystem.cs | 16 ++++++++++- .../Preferences/HumanoidCharacterProfile.cs | 6 ++--- .../Loadouts/Effects/GroupLoadoutEffect.cs | 2 +- .../Effects/JobRequirementLoadoutEffect.cs | 8 +++++- .../Loadouts/Effects/LoadoutEffect.cs | 2 +- .../Effects/PointsCostLoadoutEffect.cs | 2 +- .../Loadouts/Effects/SpeciesLoadoutEffect.cs | 2 +- .../Preferences/Loadouts/RoleLoadout.cs | 27 +++++++++++++++---- 11 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index aa66b7731d..e4a13ed8c6 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -294,7 +294,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered(LoadoutSystem.GetJobPrototype(job.ID))) { - var loadout = profile.GetLoadoutOrDefault(LoadoutSystem.GetJobPrototype(job.ID), profile.Species, EntityManager, _prototypeManager); + var loadout = profile.GetLoadoutOrDefault(LoadoutSystem.GetJobPrototype(job.ID), _playerManager.LocalSession, profile.Species, EntityManager, _prototypeManager); GiveDummyLoadout(dummy, loadout); } } @@ -414,7 +414,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered(LoadoutSystem.GetJobPrototype(job.ID))) { - var loadout = humanoid.GetLoadoutOrDefault(LoadoutSystem.GetJobPrototype(job.ID), humanoid.Species, EntityManager, _prototypeManager); + var loadout = humanoid.GetLoadoutOrDefault(LoadoutSystem.GetJobPrototype(job.ID), _playerManager.LocalSession, humanoid.Species, EntityManager, _prototypeManager); GiveDummyLoadout(dummyEnt, loadout); } } diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs index 18f986fc7d..e8e619ae6d 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs @@ -946,7 +946,7 @@ namespace Content.Client.Lobby.UI if (loadout == null) { loadout = new RoleLoadout(roleLoadoutProto.ID); - loadout.SetDefault(_prototypeManager); + loadout.SetDefault(Profile, _playerManager.LocalSession, _prototypeManager); } OpenLoadout(job, loadout, roleLoadoutProto); diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index d30c9fc111..e960a2bbbe 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -26,6 +26,7 @@ using Content.Shared.StatusIcon; using JetBrains.Annotations; using Robust.Shared.Configuration; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -39,18 +40,18 @@ namespace Content.Server.Station.Systems; [PublicAPI] public sealed class StationSpawningSystem : SharedStationSpawningSystem { + [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly IConfigurationManager _configurationManager = default!; - [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; - [Dependency] private readonly IdCardSystem _cardSystem = default!; - [Dependency] private readonly PdaSystem _pdaSystem = default!; - [Dependency] private readonly SharedAccessSystem _accessSystem = default!; - [Dependency] private readonly IdentitySystem _identity = default!; - [Dependency] private readonly MetaDataSystem _metaSystem = default!; - + [Dependency] private readonly ActorSystem _actors = default!; [Dependency] private readonly ArrivalsSystem _arrivalsSystem = default!; [Dependency] private readonly ContainerSpawnPointSystem _containerSpawnPointSystem = default!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; + [Dependency] private readonly IdCardSystem _cardSystem = default!; + [Dependency] private readonly IdentitySystem _identity = default!; + [Dependency] private readonly MetaDataSystem _metaSystem = default!; + [Dependency] private readonly PdaSystem _pdaSystem = default!; + [Dependency] private readonly SharedAccessSystem _accessSystem = default!; private bool _randomizeCharacters; @@ -198,7 +199,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem if (loadout == null) { loadout = new RoleLoadout(jobLoadout); - loadout.SetDefault(_prototypeManager); + loadout.SetDefault(profile, _actors.GetSession(entity), _prototypeManager); } EquipRoleLoadout(entity.Value, loadout, roleProto); diff --git a/Content.Shared/Clothing/LoadoutSystem.cs b/Content.Shared/Clothing/LoadoutSystem.cs index 3136b4b4b3..f1b1dc36d9 100644 --- a/Content.Shared/Clothing/LoadoutSystem.cs +++ b/Content.Shared/Clothing/LoadoutSystem.cs @@ -1,8 +1,11 @@ using System.Linq; using Content.Shared.Clothing.Components; +using Content.Shared.Humanoid; +using Content.Shared.Preferences; using Content.Shared.Preferences.Loadouts; using Content.Shared.Roles; using Content.Shared.Station; +using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -15,6 +18,7 @@ public sealed class LoadoutSystem : EntitySystem { // Shared so we can predict it for placement manager. + [Dependency] private readonly ActorSystem _actors = default!; [Dependency] private readonly SharedStationSpawningSystem _station = default!; [Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -125,7 +129,17 @@ public sealed class LoadoutSystem : EntitySystem var id = _random.Pick(component.RoleLoadout); var proto = _protoMan.Index(id); var loadout = new RoleLoadout(id); - loadout.SetDefault(_protoMan, true); + loadout.SetDefault(GetProfile(uid), _actors.GetSession(uid), _protoMan, true); _station.EquipRoleLoadout(uid, loadout, proto); } + + public HumanoidCharacterProfile GetProfile(EntityUid? uid) + { + if (TryComp(uid, out HumanoidAppearanceComponent? appearance)) + { + return HumanoidCharacterProfile.DefaultWithSpecies(appearance.Species); + } + + return HumanoidCharacterProfile.Random(); + } } diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index fd95848d2c..22b4ed9815 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -690,15 +690,15 @@ namespace Content.Shared.Preferences return profile; } - public RoleLoadout GetLoadoutOrDefault(string id, ProtoId? species, IEntityManager entManager, IPrototypeManager protoManager) + public RoleLoadout GetLoadoutOrDefault(string id, ICommonSession? session, ProtoId? species, IEntityManager entManager, IPrototypeManager protoManager) { if (!_loadouts.TryGetValue(id, out var loadout)) { loadout = new RoleLoadout(id); - loadout.SetDefault(protoManager, force: true); + loadout.SetDefault(this, session, protoManager, force: true); } - loadout.SetDefault(protoManager); + loadout.SetDefault(this, session, protoManager); return loadout; } diff --git a/Content.Shared/Preferences/Loadouts/Effects/GroupLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/GroupLoadoutEffect.cs index 258d9a4dbb..47e3bea771 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/GroupLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/GroupLoadoutEffect.cs @@ -13,7 +13,7 @@ public sealed partial class GroupLoadoutEffect : LoadoutEffect [DataField(required: true)] public ProtoId Proto; - public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) + public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession? session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { var effectsProto = collection.Resolve().Index(Proto); diff --git a/Content.Shared/Preferences/Loadouts/Effects/JobRequirementLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/JobRequirementLoadoutEffect.cs index 54576d3a53..4a40e2c65e 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/JobRequirementLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/JobRequirementLoadoutEffect.cs @@ -15,8 +15,14 @@ public sealed partial class JobRequirementLoadoutEffect : LoadoutEffect [DataField(required: true)] public JobRequirement Requirement = default!; - public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) + public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession? session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { + if (session == null) + { + reason = FormattedMessage.Empty; + return true; + } + var manager = collection.Resolve(); var playtimes = manager.GetPlayTimes(session); return JobRequirements.TryRequirementMet(Requirement, playtimes, out reason, diff --git a/Content.Shared/Preferences/Loadouts/Effects/LoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/LoadoutEffect.cs index f35b14e2e0..a9cbfc5fd5 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/LoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/LoadoutEffect.cs @@ -13,7 +13,7 @@ public abstract partial class LoadoutEffect public abstract bool Validate( HumanoidCharacterProfile profile, RoleLoadout loadout, - ICommonSession session, + ICommonSession? session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason); diff --git a/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs index 842b4cfc03..734dc25ba4 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs @@ -13,7 +13,7 @@ public sealed partial class PointsCostLoadoutEffect : LoadoutEffect public override bool Validate( HumanoidCharacterProfile profile, RoleLoadout loadout, - ICommonSession session, + ICommonSession? session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { diff --git a/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs b/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs index 8f886dd2ab..4ec46a8348 100644 --- a/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs +++ b/Content.Shared/Preferences/Loadouts/Effects/SpeciesLoadoutEffect.cs @@ -11,7 +11,7 @@ public sealed partial class SpeciesLoadoutEffect : LoadoutEffect [DataField(required: true)] public List> Species = new(); - public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, + public override bool Validate(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession? session, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { if (Species.Contains(profile.Species)) diff --git a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs index d2fc8df559..d02929cd96 100644 --- a/Content.Shared/Preferences/Loadouts/RoleLoadout.cs +++ b/Content.Shared/Preferences/Loadouts/RoleLoadout.cs @@ -166,12 +166,15 @@ public sealed partial class RoleLoadout : IEquatable /// /// Resets the selected loadouts to default if no data is present. /// - /// Clear existing data first - public void SetDefault(IPrototypeManager protoManager, bool force = false) + public void SetDefault(HumanoidCharacterProfile? profile, ICommonSession? session, IPrototypeManager protoManager, bool force = false) { + if (profile == null) + return; + if (force) SelectedLoadouts.Clear(); + var collection = IoCManager.Instance!; var roleProto = protoManager.Index(Role); for (var i = roleProto.Groups.Count - 1; i >= 0; i--) @@ -184,14 +187,28 @@ public sealed partial class RoleLoadout : IEquatable if (SelectedLoadouts.ContainsKey(group)) continue; - SelectedLoadouts[group] = new List(); + var loadouts = new List(); + SelectedLoadouts[group] = loadouts; if (groupProto.MinLimit > 0) { // Apply any loadouts we can. for (var j = 0; j < Math.Min(groupProto.MinLimit, groupProto.Loadouts.Count); j++) { - AddLoadout(group, groupProto.Loadouts[j], protoManager); + if (!protoManager.TryIndex(groupProto.Loadouts[j], out var loadoutProto)) + continue; + + var defaultLoadout = new Loadout() + { + Prototype = loadoutProto.ID, + }; + + // Not valid so don't default to it anyway. + if (!IsValid(profile, session, defaultLoadout.Prototype, collection, out _)) + continue; + + loadouts.Add(defaultLoadout); + Apply(loadoutProto); } } } @@ -200,7 +217,7 @@ public sealed partial class RoleLoadout : IEquatable /// /// Returns whether a loadout is valid or not. /// - public bool IsValid(HumanoidCharacterProfile profile, ICommonSession session, ProtoId loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) + public bool IsValid(HumanoidCharacterProfile profile, ICommonSession? session, ProtoId loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) { reason = null;