Files
OldThink/Content.Shared/Preferences/HumanoidCharacterProfile.cs
ThereDrD0 0d99c5afe7 Фиксы (#488)
* add material storage component to whitemoose

* fix pickaxe inventory size

* fix free sponsor only races

* invisible aghost no longer visible in ghost warp menu

* add migration for BoxTrashbag

* fix make wizard admin verb

* fixed wizard components swap and new wizard marks as wizard in ghost warp menu now

* Stop eating food if you drop it (#29854)

* Stop eating food if you drop it

* woops, unused param

* comments

---------

Co-authored-by: plykiya <plykiya@protonmail.com>

* Eating and Drinking Doafter Change (#30060)

My lawyer told me to do this

Co-authored-by: plykiya <plykiya@protonmail.com>

* ActivatableUI tweaks (#27448)

* ActivatableUI tweaks

* EntGotRemovedFromContainerMessage

* A

* Revert "ActivatableUI tweaks (#27448)"

This reverts commit 5b311c6fdbf77db6838bdcf9993b98272d4ebeac.

* fix eating food from containers

* fix double captain duffel

* add bible for chaplain loadout

* possible bad fix for double security headsets

---------

Co-authored-by: Plykiya <58439124+Plykiya@users.noreply.github.com>
Co-authored-by: plykiya <plykiya@protonmail.com>
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
2024-07-24 02:19:13 +03:00

822 lines
30 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Linq;
using System.Globalization;
using System.Text.RegularExpressions;
using Content.Shared.CCVar;
using Content.Shared.GameTicking;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Preferences.Loadouts.Effects;
using Content.Shared.Roles;
using Content.Shared.Traits;
using Content.Shared._White.TTS;
using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Preferences
{
/// <summary>
/// Character profile. Looks immutable, but uses non-immutable semantics internally for serialization/code sanity purposes.
/// </summary>
[DataDefinition]
[Serializable, NetSerializable]
public sealed partial class HumanoidCharacterProfile : ICharacterProfile
{
public const int MaxNameLength = 32;
public const int MaxDescLength = 512;
private readonly Dictionary<string, JobPriority> _jobPriorities;
private readonly List<string> _antagPreferences;
private readonly List<string> _traitPreferences;
public IReadOnlyDictionary<string, RoleLoadout> Loadouts => _loadouts;
private Dictionary<string, RoleLoadout> _loadouts;
// What in the lord is happening here.
private HumanoidCharacterProfile(
string name,
string clownName,
string mimeName,
string borgName,
string flavortext,
string species,
string voice,
int age,
Sex sex,
Gender gender,
ProtoId<BodyTypePrototype> bodyType,
HumanoidCharacterAppearance appearance,
SpawnPriorityPreference spawnPriority,
Dictionary<string, JobPriority> jobPriorities,
PreferenceUnavailableMode preferenceUnavailable,
List<string> antagPreferences,
List<string> traitPreferences,
Dictionary<string, RoleLoadout> loadouts)
{
Name = name;
ClownName = clownName;
MimeName = mimeName;
BorgName = borgName;
FlavorText = flavortext;
Species = species;
Voice = voice;
Age = age;
Sex = sex;
Gender = gender;
BodyType = bodyType;
Appearance = appearance;
SpawnPriority = spawnPriority;
_jobPriorities = jobPriorities;
PreferenceUnavailable = preferenceUnavailable;
_antagPreferences = antagPreferences;
_traitPreferences = traitPreferences;
_loadouts = loadouts;
}
/// <summary>Copy constructor but with overridable references (to prevent useless copies)</summary>
private HumanoidCharacterProfile(
HumanoidCharacterProfile other,
Dictionary<string, JobPriority> jobPriorities,
List<string> antagPreferences,
List<string> traitPreferences,
Dictionary<string, RoleLoadout> loadouts)
: this(other.Name,
other.ClownName,
other.MimeName,
other.BorgName,
other.FlavorText,
other.Species,
other.Voice,
other.Age,
other.Sex,
other.Gender,
other.BodyType,
other.Appearance,
other.SpawnPriority,
jobPriorities,
other.PreferenceUnavailable,
antagPreferences,
traitPreferences,
loadouts)
{
}
/// <summary>Copy constructor</summary>
private HumanoidCharacterProfile(HumanoidCharacterProfile other)
: this(other, new Dictionary<string, JobPriority>(other.JobPriorities), new List<string>(other.AntagPreferences), new List<string>(other.TraitPreferences), new Dictionary<string, RoleLoadout>(other.Loadouts))
{
}
public HumanoidCharacterProfile(
string name,
string clownName,
string mimeName,
string borgName,
string flavortext,
string species,
string voice,
int age,
Sex sex,
Gender gender,
ProtoId<BodyTypePrototype> bodyType,
HumanoidCharacterAppearance appearance,
SpawnPriorityPreference spawnPriority,
IReadOnlyDictionary<string, JobPriority> jobPriorities,
PreferenceUnavailableMode preferenceUnavailable,
IReadOnlyList<string> antagPreferences,
IReadOnlyList<string> traitPreferences,
Dictionary<string, RoleLoadout> loadouts)
: this(name, clownName, mimeName, borgName, flavortext, species, voice, age, sex, gender, bodyType,
appearance, spawnPriority, new Dictionary<string, JobPriority>(jobPriorities),
preferenceUnavailable, new List<string>(antagPreferences), new List<string>(traitPreferences), new Dictionary<string, RoleLoadout>(loadouts))
{
}
/// <summary>
/// Get the default humanoid character profile, using internal constant values.
/// Defaults to <see cref="SharedHumanoidAppearanceSystem.DefaultSpecies"/> for the species.
/// </summary>
/// <returns></returns>
public HumanoidCharacterProfile() : this(
"John Doe",
"HONK",
"Quiet",
"Silicon",
"",
SharedHumanoidAppearanceSystem.DefaultSpecies,
SharedHumanoidAppearanceSystem.DefaultVoice,
18,
Sex.Male,
Gender.Male,
SharedHumanoidAppearanceSystem.DefaultBodyType,
new HumanoidCharacterAppearance(),
SpawnPriorityPreference.None,
new Dictionary<string, JobPriority>
{
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High }
},
PreferenceUnavailableMode.SpawnAsOverflow,
new List<string>(),
new List<string>(),
new Dictionary<string, RoleLoadout>())
{
}
/// <summary>
/// Return a default character profile, based on species.
/// </summary>
/// <param name="species">The species to use in this default profile. The default species is <see cref="SharedHumanoidAppearanceSystem.DefaultSpecies"/>.</param>
/// <returns>Humanoid character profile with default settings.</returns>
public static HumanoidCharacterProfile DefaultWithSpecies(string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
{
return new(
"John Doe",
"HONK",
"Quiet",
"Silicon",
"",
species,
SharedHumanoidAppearanceSystem.DefaultVoice,
18,
Sex.Male,
Gender.Male,
SharedHumanoidAppearanceSystem.DefaultBodyType,
HumanoidCharacterAppearance.DefaultWithSpecies(species),
SpawnPriorityPreference.None,
new Dictionary<string, JobPriority>
{
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High }
},
PreferenceUnavailableMode.SpawnAsOverflow,
new List<string>(),
new List<string>(),
new Dictionary<string, RoleLoadout>());
}
// TODO: This should eventually not be a visual change only.
public static HumanoidCharacterProfile Random(HashSet<string>? ignoredSpecies = null, bool includeSponsor = false)
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var random = IoCManager.Resolve<IRobustRandom>();
// WD edit - fix free sponsor species
var speciesToIgnore = ignoredSpecies != null
? new HashSet<string>(ignoredSpecies)
: new HashSet<string>();
if (!includeSponsor)
{
var sponsorSpecies = prototypeManager.EnumeratePrototypes<SpeciesPrototype>()
.Where(x => x.SponsorOnly)
.Select(x => x.ID);
speciesToIgnore.UnionWith(sponsorSpecies);
}
var species = random.Pick(prototypeManager
.EnumeratePrototypes<SpeciesPrototype>()
.Where(x => !x.SponsorOnly && x.RoundStart && !speciesToIgnore.Contains(x.ID))
.ToArray()
).ID;
// WD edit end
return RandomWithSpecies(species);
}
public static HumanoidCharacterProfile RandomWithSpecies(string species = SharedHumanoidAppearanceSystem.DefaultSpecies)
{
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
var random = IoCManager.Resolve<IRobustRandom>();
var sex = Sex.Unsexed;
var age = 18;
var bodyType = SharedHumanoidAppearanceSystem.DefaultBodyType;
if (prototypeManager.TryIndex<SpeciesPrototype>(species, out var speciesPrototype))
{
bodyType = speciesPrototype.BodyTypes[0];
sex = random.Pick(speciesPrototype.Sexes);
age = random.Next(speciesPrototype.MinAge, speciesPrototype.OldAge); // people don't look and keep making 119 year old characters with zero rp, cap it at middle aged
}
var voiceId = random.Pick(prototypeManager
.EnumeratePrototypes<TTSVoicePrototype>()
.Where(o => CanHaveVoice(o, sex)).ToArray()
).ID;
var gender = Gender.Epicene;
switch (sex)
{
case Sex.Male:
gender = Gender.Male;
break;
case Sex.Female:
gender = Gender.Female;
break;
}
var name = GetName(species, gender);
var clownName = GetClownName();
var mimeName = GetMimeName();
var borgName = GetBorgName();
return new HumanoidCharacterProfile(name, clownName, mimeName, borgName, "", species, voiceId, age, sex,
gender, bodyType, HumanoidCharacterAppearance.Random(species, sex), SpawnPriorityPreference.None,
new Dictionary<string, JobPriority>
{
{ SharedGameTicker.FallbackOverflowJob, JobPriority.High },
}, PreferenceUnavailableMode.StayInLobby, new List<string>(), new List<string>(), new Dictionary<string, RoleLoadout>());
}
public string Name { get; private set; }
public string ClownName { get; private set; }
public string MimeName { get; private set; }
public string BorgName { get; private set; }
public string FlavorText { get; private set; }
public string Species { get; private set; }
public string Voice { get; private set; }
[DataField("age")]
public int Age { get; private set; }
[DataField("sex")]
public Sex Sex { get; private set; }
[DataField("gender")]
public Gender Gender { get; private set; }
[DataField]
public ProtoId<BodyTypePrototype> BodyType { get; private set; }
public ICharacterAppearance CharacterAppearance => Appearance;
[DataField("appearance")]
public HumanoidCharacterAppearance Appearance { get; private set; }
public SpawnPriorityPreference SpawnPriority { get; private set; }
public IReadOnlyDictionary<string, JobPriority> JobPriorities => _jobPriorities;
public IReadOnlyList<string> AntagPreferences => _antagPreferences;
public IReadOnlyList<string> TraitPreferences => _traitPreferences;
public PreferenceUnavailableMode PreferenceUnavailable { get; private set; }
public HumanoidCharacterProfile WithVoice(string voice)
{
return new HumanoidCharacterProfile(this) { Voice = voice };
}
public HumanoidCharacterProfile WithBodyType(string bodyType)
{
return new HumanoidCharacterProfile(this) { BodyType = bodyType };
}
public HumanoidCharacterProfile WithName(string name)
{
return new HumanoidCharacterProfile(this) { Name = name };
}
public HumanoidCharacterProfile WithClownName(string name)
{
return new HumanoidCharacterProfile(this) { ClownName = name };
}
public HumanoidCharacterProfile WithMimeName(string name)
{
return new HumanoidCharacterProfile(this) { MimeName = name };
}
public HumanoidCharacterProfile WithBorgName(string name)
{
return new HumanoidCharacterProfile(this) { BorgName = name };
}
public HumanoidCharacterProfile WithFlavorText(string flavorText)
{
return new(this) { FlavorText = flavorText };
}
public HumanoidCharacterProfile WithAge(int age)
{
return new(this) { Age = age };
}
public HumanoidCharacterProfile WithSex(Sex sex)
{
return new(this) { Sex = sex };
}
public HumanoidCharacterProfile WithGender(Gender gender)
{
return new(this) { Gender = gender };
}
public HumanoidCharacterProfile WithSpecies(string species)
{
return new(this) { Species = species };
}
public HumanoidCharacterProfile WithCharacterAppearance(HumanoidCharacterAppearance appearance)
{
return new(this) { Appearance = appearance };
}
public HumanoidCharacterProfile WithSpawnPriorityPreference(SpawnPriorityPreference spawnPriority)
{
return new(this) { SpawnPriority = spawnPriority };
}
public HumanoidCharacterProfile WithJobPriorities(IEnumerable<KeyValuePair<string, JobPriority>> jobPriorities)
{
return new(this, new Dictionary<string, JobPriority>(jobPriorities), _antagPreferences, _traitPreferences, _loadouts);
}
public HumanoidCharacterProfile WithJobPriority(string jobId, JobPriority priority)
{
var dictionary = new Dictionary<string, JobPriority>(_jobPriorities);
if (priority == JobPriority.Never)
{
dictionary.Remove(jobId);
}
else
{
dictionary[jobId] = priority;
}
return new(this, dictionary, _antagPreferences, _traitPreferences, _loadouts);
}
public HumanoidCharacterProfile WithPreferenceUnavailable(PreferenceUnavailableMode mode)
{
return new(this) { PreferenceUnavailable = mode };
}
public HumanoidCharacterProfile WithAntagPreferences(IEnumerable<string> antagPreferences)
{
return new(this, _jobPriorities, new List<string>(antagPreferences), _traitPreferences, _loadouts);
}
public HumanoidCharacterProfile WithAntagPreference(string antagId, bool pref)
{
var list = new List<string>(_antagPreferences);
if (pref)
{
if (!list.Contains(antagId))
{
list.Add(antagId);
}
}
else
{
list.Remove(antagId);
}
return new(this, _jobPriorities, list, _traitPreferences, _loadouts);
}
public HumanoidCharacterProfile WithTraitPreference(string traitId, bool pref)
{
var list = new List<string>(_traitPreferences);
// TODO: Maybe just refactor this to HashSet? Same with _antagPreferences
if (pref)
{
if (!list.Contains(traitId))
{
list.Add(traitId);
}
}
else
{
list.Remove(traitId);
}
return new(this, _jobPriorities, _antagPreferences, list, _loadouts);
}
public string Summary =>
Loc.GetString(
"humanoid-character-profile-summary",
("name", Name),
("gender", Gender.ToString().ToLowerInvariant()),
("age", Age)
);
public bool MemberwiseEquals(ICharacterProfile maybeOther)
{
if (maybeOther is not HumanoidCharacterProfile other) return false;
if (Name != other.Name) return false;
if (ClownName != other.ClownName) return false;
if (MimeName != other.MimeName) return false;
if (BorgName != other.BorgName) return false;
if (Age != other.Age) return false;
if (Sex != other.Sex) return false;
if (Gender != other.Gender) return false;
if (BodyType != other.BodyType) return false;
if (PreferenceUnavailable != other.PreferenceUnavailable) return false;
if (SpawnPriority != other.SpawnPriority) return false;
if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false;
if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false;
if (!_traitPreferences.SequenceEqual(other._traitPreferences)) return false;
if (!Loadouts.SequenceEqual(other.Loadouts)) return false;
return Appearance.MemberwiseEquals(other.Appearance);
}
public void EnsureValid(ICommonSession session,
IDependencyCollection collection,
string[] sponsorMarkings,
bool isAdminSpecie)
{
var configManager = collection.Resolve<IConfigurationManager>();
var prototypeManager = collection.Resolve<IPrototypeManager>();
if (!prototypeManager.TryIndex<SpeciesPrototype>(Species, out var speciesPrototype) ||
speciesPrototype.RoundStart == false)
{
Species = SharedHumanoidAppearanceSystem.DefaultSpecies;
speciesPrototype = prototypeManager.Index<SpeciesPrototype>(Species);
}
if (speciesPrototype.SponsorOnly && !sponsorMarkings.Contains(Species)
&& speciesPrototype.ForAdmins && !isAdminSpecie)
{
Species = SharedHumanoidAppearanceSystem.DefaultSpecies;
speciesPrototype = prototypeManager.Index<SpeciesPrototype>(Species);
}
var sex = Sex switch
{
Sex.Male => Sex.Male,
Sex.Female => Sex.Female,
Sex.Unsexed => Sex.Unsexed,
_ => Sex.Male // Invalid enum values.
};
// ensure the species can be that sex and their age fits the founds
if (!speciesPrototype.Sexes.Contains(sex))
sex = speciesPrototype.Sexes[0];
var age = Math.Clamp(Age, speciesPrototype.MinAge, speciesPrototype.MaxAge);
if (!prototypeManager.TryIndex<BodyTypePrototype>(BodyType, out var bodyType) ||
!SharedHumanoidAppearanceSystem.IsBodyTypeValid(bodyType, speciesPrototype, Sex))
{
BodyType =
prototypeManager.Index<BodyTypePrototype>(SharedHumanoidAppearanceSystem.DefaultBodyType).ID;
}
var gender = Gender switch
{
Gender.Epicene => Gender.Epicene,
Gender.Female => Gender.Female,
Gender.Male => Gender.Male,
Gender.Neuter => Gender.Neuter,
_ => Gender.Epicene // Invalid enum values.
};
string name;
string clownName;
string mimeName;
string borgName;
if (string.IsNullOrEmpty(Name))
{
name = GetName(Species, gender);
}
else if (Name.Length > MaxNameLength)
{
name = Name[..MaxNameLength];
}
else
{
name = Name;
}
if (string.IsNullOrEmpty(ClownName))
{
clownName = GetClownName();
}
else if (ClownName.Length > MaxNameLength)
{
clownName = ClownName[..MaxNameLength];
}
else
{
clownName = ClownName;
}
if (string.IsNullOrEmpty(MimeName))
{
mimeName = GetMimeName();
}
else if (MimeName.Length > MaxNameLength)
{
mimeName = MimeName[..MaxNameLength];
}
else
{
mimeName = MimeName;
}
if (string.IsNullOrEmpty(BorgName))
{
borgName = GetBorgName();
}
else if (BorgName.Length > MaxNameLength)
{
borgName = BorgName[..MaxNameLength];
}
else
{
borgName = BorgName;
}
name = name.Trim();
clownName = clownName.Trim();
mimeName = mimeName.Trim();
borgName = borgName.Trim();
if (configManager.GetCVar(CCVars.RestrictedNames))
{
name = Regex.Replace(name, @"[^А-Я,а-я,0-9, -]", string.Empty); //WD EDIT
clownName = Regex.Replace(clownName, @"[^А-Я,а-я,0-9, -]", string.Empty);
mimeName = Regex.Replace(mimeName, @"[^А-Я,а-я,0-9, -]", string.Empty);
borgName = Regex.Replace(borgName, @"[^А-Я,а-я,0-9, -]", string.Empty);
}
if (configManager.GetCVar(CCVars.ICNameCase))
{
// This regex replaces the first character of the first and last words of the name with their uppercase version
name = Regex.Replace(name,
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
m => m.Groups["word"].Value.ToUpper());
clownName = Regex.Replace(clownName,
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
m => m.Groups["word"].Value.ToUpper());
mimeName = Regex.Replace(mimeName,
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
m => m.Groups["word"].Value.ToUpper());
borgName = Regex.Replace(borgName,
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
m => m.Groups["word"].Value.ToUpper());
}
if (string.IsNullOrEmpty(name))
{
name = GetName(Species, gender);
clownName = GetClownName();
mimeName = GetMimeName();
borgName = GetBorgName();
}
var flavortext = FlavorText.Length > MaxDescLength
? FormattedMessage.RemoveMarkup(FlavorText)[..MaxDescLength]
: FormattedMessage.RemoveMarkup(FlavorText);
// WD-EDIT
var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, BodyType, sponsorMarkings);
// WD-EDIT
var prefsUnavailableMode = PreferenceUnavailable switch
{
PreferenceUnavailableMode.StayInLobby => PreferenceUnavailableMode.StayInLobby,
PreferenceUnavailableMode.SpawnAsOverflow => PreferenceUnavailableMode.SpawnAsOverflow,
_ => PreferenceUnavailableMode.StayInLobby // Invalid enum values.
};
var spawnPriority = SpawnPriority switch
{
SpawnPriorityPreference.None => SpawnPriorityPreference.None,
SpawnPriorityPreference.Arrivals => SpawnPriorityPreference.Arrivals,
SpawnPriorityPreference.Cryosleep => SpawnPriorityPreference.Cryosleep,
_ => SpawnPriorityPreference.None // Invalid enum values.
};
var priorities = new Dictionary<string, JobPriority>(JobPriorities
.Where(p => prototypeManager.TryIndex<JobPrototype>(p.Key, out var job) && job.SetPreference &&
p.Value switch
{
JobPriority.Never => false, // Drop never since that's assumed default.
JobPriority.Low => true,
JobPriority.Medium => true,
JobPriority.High => true,
_ => false
}));
var antags = AntagPreferences
.Where(id => prototypeManager.TryIndex<AntagPrototype>(id, out var antag) && antag.SetPreference)
.ToList();
var traits = TraitPreferences
.Where(prototypeManager.HasIndex<TraitPrototype>)
.ToList();
Name = name;
ClownName = clownName;
MimeName = mimeName;
BorgName = borgName;
FlavorText = flavortext;
Age = age;
Sex = sex;
Gender = gender;
Appearance = appearance;
SpawnPriority = spawnPriority;
_jobPriorities.Clear();
foreach (var (job, priority) in priorities)
{
_jobPriorities.Add(job, priority);
}
PreferenceUnavailable = prefsUnavailableMode;
_antagPreferences.Clear();
_antagPreferences.AddRange(antags);
_traitPreferences.Clear();
_traitPreferences.AddRange(traits);
prototypeManager.TryIndex<TTSVoicePrototype>(Voice, out var voice);
if (voice is null)
Voice = SharedHumanoidAppearanceSystem.DefaultSexVoice[sex];
// Checks prototypes exist for all loadouts and dump / set to default if not.
var toRemove = new ValueList<string>();
foreach (var (roleName, loadouts) in _loadouts)
{
if (!prototypeManager.HasIndex<RoleLoadoutPrototype>(roleName))
{
toRemove.Add(roleName);
continue;
}
loadouts.EnsureValid(session, collection);
}
foreach (var value in toRemove)
{
_loadouts.Remove(value);
}
}
public static bool CanHaveVoice(TTSVoicePrototype voice, Sex sex)
{
return voice.RoundStart && sex == Sex.Unsexed || (voice.Sex == sex || voice.Sex == Sex.Unsexed);
}
public ICharacterProfile Validated(ICommonSession session, IDependencyCollection collection, string[] sponsorMarkings, bool isAdminSpecie)
{
var profile = new HumanoidCharacterProfile(this);
profile.EnsureValid(session, collection, sponsorMarkings, isAdminSpecie);
return profile;
}
// sorry this is kind of weird and duplicated,
/// working inside these non entity systems is a bit wack
public static string GetName(string species, Gender gender)
{
var namingSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<NamingSystem>();
return namingSystem.GetName(species, gender);
}
public static string GetClownName()
{
var namingSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<NamingSystem>();
return namingSystem.GetClownName();
}
public static string GetMimeName()
{
var namingSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<NamingSystem>();
return namingSystem.GetMimeName();
}
public static string GetBorgName()
{
var namingSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<NamingSystem>();
return namingSystem.GetBorgName();
}
public override bool Equals(object? obj)
{
return obj is HumanoidCharacterProfile other && MemberwiseEquals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(
HashCode.Combine(
Name,
Species,
Age,
Sex,
Gender,
Appearance
),
HashCode.Combine(
ClownName,
MimeName,
BorgName
),
SpawnPriority,
PreferenceUnavailable,
_jobPriorities,
_antagPreferences,
_traitPreferences,
_loadouts
);
}
public void SetLoadout(RoleLoadout loadout)
{
_loadouts[loadout.Role.Id] = loadout;
}
public HumanoidCharacterProfile WithLoadout(RoleLoadout loadout)
{
// Deep copies so we don't modify the DB profile.
var copied = new Dictionary<string, RoleLoadout>();
foreach (var proto in _loadouts)
{
if (proto.Key == loadout.Role)
continue;
copied[proto.Key] = proto.Value.Clone();
}
copied[loadout.Role] = loadout.Clone();
return new(this, _jobPriorities, _antagPreferences, _traitPreferences, copied);
}
public RoleLoadout GetLoadoutOrDefault(string id, IEntityManager entManager, IPrototypeManager protoManager)
{
if (!_loadouts.TryGetValue(id, out var loadout))
{
loadout = new RoleLoadout(id);
loadout.SetDefault(protoManager, force: true);
}
loadout.SetDefault(protoManager);
return loadout;
}
}
}