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
This commit is contained in:
metalgearsloth
2024-06-15 16:53:42 +10:00
committed by GitHub
parent f0fbedd640
commit 8f12e90b90
11 changed files with 64 additions and 26 deletions

View File

@@ -294,7 +294,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(LoadoutSystem.GetJobPrototype(job.ID))) if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(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); GiveDummyLoadout(dummy, loadout);
} }
} }
@@ -414,7 +414,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(LoadoutSystem.GetJobPrototype(job.ID))) if (_prototypeManager.HasIndex<RoleLoadoutPrototype>(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); GiveDummyLoadout(dummyEnt, loadout);
} }
} }

View File

@@ -946,7 +946,7 @@ namespace Content.Client.Lobby.UI
if (loadout == null) if (loadout == null)
{ {
loadout = new RoleLoadout(roleLoadoutProto.ID); loadout = new RoleLoadout(roleLoadoutProto.ID);
loadout.SetDefault(_prototypeManager); loadout.SetDefault(Profile, _playerManager.LocalSession, _prototypeManager);
} }
OpenLoadout(job, loadout, roleLoadoutProto); OpenLoadout(job, loadout, roleLoadoutProto);

View File

@@ -26,6 +26,7 @@ using Content.Shared.StatusIcon;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -39,18 +40,18 @@ namespace Content.Server.Station.Systems;
[PublicAPI] [PublicAPI]
public sealed class StationSpawningSystem : SharedStationSpawningSystem public sealed class StationSpawningSystem : SharedStationSpawningSystem
{ {
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly ActorSystem _actors = 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 ArrivalsSystem _arrivalsSystem = default!; [Dependency] private readonly ArrivalsSystem _arrivalsSystem = default!;
[Dependency] private readonly ContainerSpawnPointSystem _containerSpawnPointSystem = 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; private bool _randomizeCharacters;
@@ -198,7 +199,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
if (loadout == null) if (loadout == null)
{ {
loadout = new RoleLoadout(jobLoadout); loadout = new RoleLoadout(jobLoadout);
loadout.SetDefault(_prototypeManager); loadout.SetDefault(profile, _actors.GetSession(entity), _prototypeManager);
} }
EquipRoleLoadout(entity.Value, loadout, roleProto); EquipRoleLoadout(entity.Value, loadout, roleProto);

View File

@@ -1,8 +1,11 @@
using System.Linq; using System.Linq;
using Content.Shared.Clothing.Components; using Content.Shared.Clothing.Components;
using Content.Shared.Humanoid;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts; using Content.Shared.Preferences.Loadouts;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.Station; using Content.Shared.Station;
using Robust.Shared.Player;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
@@ -15,6 +18,7 @@ public sealed class LoadoutSystem : EntitySystem
{ {
// Shared so we can predict it for placement manager. // Shared so we can predict it for placement manager.
[Dependency] private readonly ActorSystem _actors = default!;
[Dependency] private readonly SharedStationSpawningSystem _station = default!; [Dependency] private readonly SharedStationSpawningSystem _station = default!;
[Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
@@ -125,7 +129,17 @@ public sealed class LoadoutSystem : EntitySystem
var id = _random.Pick(component.RoleLoadout); var id = _random.Pick(component.RoleLoadout);
var proto = _protoMan.Index(id); var proto = _protoMan.Index(id);
var loadout = new RoleLoadout(id); var loadout = new RoleLoadout(id);
loadout.SetDefault(_protoMan, true); loadout.SetDefault(GetProfile(uid), _actors.GetSession(uid), _protoMan, true);
_station.EquipRoleLoadout(uid, loadout, proto); _station.EquipRoleLoadout(uid, loadout, proto);
} }
public HumanoidCharacterProfile GetProfile(EntityUid? uid)
{
if (TryComp(uid, out HumanoidAppearanceComponent? appearance))
{
return HumanoidCharacterProfile.DefaultWithSpecies(appearance.Species);
}
return HumanoidCharacterProfile.Random();
}
} }

View File

@@ -690,15 +690,15 @@ namespace Content.Shared.Preferences
return profile; return profile;
} }
public RoleLoadout GetLoadoutOrDefault(string id, ProtoId<SpeciesPrototype>? species, IEntityManager entManager, IPrototypeManager protoManager) public RoleLoadout GetLoadoutOrDefault(string id, ICommonSession? session, ProtoId<SpeciesPrototype>? species, IEntityManager entManager, IPrototypeManager protoManager)
{ {
if (!_loadouts.TryGetValue(id, out var loadout)) if (!_loadouts.TryGetValue(id, out var loadout))
{ {
loadout = new RoleLoadout(id); 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; return loadout;
} }

View File

@@ -13,7 +13,7 @@ public sealed partial class GroupLoadoutEffect : LoadoutEffect
[DataField(required: true)] [DataField(required: true)]
public ProtoId<LoadoutEffectGroupPrototype> Proto; public ProtoId<LoadoutEffectGroupPrototype> 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<IPrototypeManager>().Index(Proto); var effectsProto = collection.Resolve<IPrototypeManager>().Index(Proto);

View File

@@ -15,8 +15,14 @@ public sealed partial class JobRequirementLoadoutEffect : LoadoutEffect
[DataField(required: true)] [DataField(required: true)]
public JobRequirement Requirement = default!; 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<ISharedPlaytimeManager>(); var manager = collection.Resolve<ISharedPlaytimeManager>();
var playtimes = manager.GetPlayTimes(session); var playtimes = manager.GetPlayTimes(session);
return JobRequirements.TryRequirementMet(Requirement, playtimes, out reason, return JobRequirements.TryRequirementMet(Requirement, playtimes, out reason,

View File

@@ -13,7 +13,7 @@ public abstract partial class LoadoutEffect
public abstract bool Validate( public abstract bool Validate(
HumanoidCharacterProfile profile, HumanoidCharacterProfile profile,
RoleLoadout loadout, RoleLoadout loadout,
ICommonSession session, ICommonSession? session,
IDependencyCollection collection, IDependencyCollection collection,
[NotNullWhen(false)] out FormattedMessage? reason); [NotNullWhen(false)] out FormattedMessage? reason);

View File

@@ -13,7 +13,7 @@ public sealed partial class PointsCostLoadoutEffect : LoadoutEffect
public override bool Validate( public override bool Validate(
HumanoidCharacterProfile profile, HumanoidCharacterProfile profile,
RoleLoadout loadout, RoleLoadout loadout,
ICommonSession session, ICommonSession? session,
IDependencyCollection collection, IDependencyCollection collection,
[NotNullWhen(false)] out FormattedMessage? reason) [NotNullWhen(false)] out FormattedMessage? reason)
{ {

View File

@@ -11,7 +11,7 @@ public sealed partial class SpeciesLoadoutEffect : LoadoutEffect
[DataField(required: true)] [DataField(required: true)]
public List<ProtoId<SpeciesPrototype>> Species = new(); public List<ProtoId<SpeciesPrototype>> 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) [NotNullWhen(false)] out FormattedMessage? reason)
{ {
if (Species.Contains(profile.Species)) if (Species.Contains(profile.Species))

View File

@@ -166,12 +166,15 @@ public sealed partial class RoleLoadout : IEquatable<RoleLoadout>
/// <summary> /// <summary>
/// Resets the selected loadouts to default if no data is present. /// Resets the selected loadouts to default if no data is present.
/// </summary> /// </summary>
/// <param name="force">Clear existing data first</param> public void SetDefault(HumanoidCharacterProfile? profile, ICommonSession? session, IPrototypeManager protoManager, bool force = false)
public void SetDefault(IPrototypeManager protoManager, bool force = false)
{ {
if (profile == null)
return;
if (force) if (force)
SelectedLoadouts.Clear(); SelectedLoadouts.Clear();
var collection = IoCManager.Instance!;
var roleProto = protoManager.Index(Role); var roleProto = protoManager.Index(Role);
for (var i = roleProto.Groups.Count - 1; i >= 0; i--) for (var i = roleProto.Groups.Count - 1; i >= 0; i--)
@@ -184,14 +187,28 @@ public sealed partial class RoleLoadout : IEquatable<RoleLoadout>
if (SelectedLoadouts.ContainsKey(group)) if (SelectedLoadouts.ContainsKey(group))
continue; continue;
SelectedLoadouts[group] = new List<Loadout>(); var loadouts = new List<Loadout>();
SelectedLoadouts[group] = loadouts;
if (groupProto.MinLimit > 0) if (groupProto.MinLimit > 0)
{ {
// Apply any loadouts we can. // Apply any loadouts we can.
for (var j = 0; j < Math.Min(groupProto.MinLimit, groupProto.Loadouts.Count); j++) 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<RoleLoadout>
/// <summary> /// <summary>
/// Returns whether a loadout is valid or not. /// Returns whether a loadout is valid or not.
/// </summary> /// </summary>
public bool IsValid(HumanoidCharacterProfile profile, ICommonSession session, ProtoId<LoadoutPrototype> loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason) public bool IsValid(HumanoidCharacterProfile profile, ICommonSession? session, ProtoId<LoadoutPrototype> loadout, IDependencyCollection collection, [NotNullWhen(false)] out FormattedMessage? reason)
{ {
reason = null; reason = null;